連載
» 2004年07月08日 00時00分 公開

JavaBeansをサーブレット/JSPから利用する基礎から学ぶサーブレット/JSP(13)(2/2 ページ)

[山田祥寛,@IT]
前のページへ 1|2       

JSPファイルからJavaBeansクラスを利用する

 さて、最後にリクエスト属性に保存されたJavaBeansクラスを、今度は「.jsp」ファイルで再び「復元」する必要があります。

JavaBeansクラスのインスタンス化〜<jsp:useBean>要素〜

 JSPからJavaBeansクラスをインスタンス化するには、<jsp:useBean>要素を使って行うことができます。result.jsp冒頭の、以下の部分に注目してみてください。

<jsp:useBean id="SendMail" class="to.msn.wings.SendMail" scope="request" />

 <jsp:useBean>要素は、第4回「JSPの基本構文を理解する」でもご紹介した<jsp:include>や<jsp:forward>と同じく、JSPに標準で用意されたアクションタグの1つです。JSPファイルの任意の個所に記述することができます。

 <jsp:useBean>要素の一般的な構文は以下のとおりです。

<jsp:useBean
  id="オブジェクト名"
  class="JavaBeansクラスの完全修飾名"
  scope="スコープの範囲" />

 さて、ここで初めて「スコープ」というキーワードが登場しました。スコープ(Scope)とは、読んでその名のとおり「変数が保持される期間・範囲」を表しますが、このスコープという概念は、複数のクラス(サーブレット・JSP)間でJavaBeansクラスを共有する場合に大変重要なものです。

 JSP&サーブレットコンテナ(Tomcat)は、JavaBeansクラスをインスタンス化するに際して、以下のような手順を踏みます。

id属性とscope属性が同一のオブジェクトが存在するか?
<Yesの場合>
   見つかったオブジェクトをそのまま再利用
<Noの場合>
   新たなインスタンス(オブジェクト)を生成

 つまり、JavaBeansクラスが同一であるかの判断は「オブジェクト名」ではなく、「オブジェクト名+スコープ」で行われるということです。いくらほかのサーブレットクラス・JSPファイルでJavaBeansクラスを保持していたとしても、スコープが一致していないJavaBeansクラスは共有することができませんので、注意してください。

 ちなみに、scope属性で指定可能な設定値は、以下のとおりです。

スコープ名 概要
page 現在のページ(ファイル)内でのみ有効。ほかのページと共有の必要がない単発的な処理を行う場合に使用する。全スコープ中で最も有効範囲の狭い設定(デフォルト)
request 一連のリクエスト処理の範囲で有効。現在のページ、およびフォワード(またはインクルード)された先のページでのみ、値を共有することができる
session ユーザーセッションの範囲で有効。複数の独立したファイル(クラス)間で情報を共有したい場合に使用する(例:ECサイトにおける買い物カゴなど)。異なるユーザーとの間では情報は共有されない
application 現在のアプリケーション内のすべてのファイル(クラス)間、アプリケーションにアクセスしている全ユーザー間で有効。全スコープ中で最も有効範囲の広い設定
表 scope属性に設定可能な値

 それぞれのスコープの違いを図示すると以下のようになります。

図2 スコープの違い 図2 スコープの違い

 より有効範囲の広いスコープを採用すれば、それだけ広範囲でデータを共有することができますが、基本的にスコープは必要最小限の範囲にとどめることが重要です。というのも、不必要に広範囲なスコープを設定することで、以下のような問題が発生する可能性があるためです。

  • 不要なデータがアプリケーション内で競合、または予期しない影響を及ぼす可能性がある
  • サーバのメモリリソースを無用に浪費する

 特に、application・sessionスコープは、分・時間単位で保持される可能性もあるため(page・requestスコープは、一般的にミリ秒・秒単位で破棄されます)、本当にそのスコープが必要なのかどうか、使用に際しては十分な検討が必要でしょう。

One Point

「.jsp」ファイルでJavaBeansクラスをインスタンス化するには、<jsp:useBean>要素を使用します。<jsp:useBean>要素は、id・scope属性が一致するJavaBeansクラスがすでに存在する場合、既存のオブジェクトをそのまま再利用します。


JavaBeansクラスのプロパティへのアクセス〜<jsp:getProperty>要素〜

 さて、サーブレットクラスで保持しておいたJavaBeansクラスが無事に復元できたところで、今度はJavaBeansクラス内のプロパティにアクセスしてみましょう。

 result.jspの以下部分に注目してみてください。

<table border="1">
 <tr>
  <th align="right" valign="top">To:</th>
  <td><jsp:getProperty name="SendMail" property="toAdd" /></td>
 </tr><tr>
  <th align="right" valign="top">Cc:</th>
  <td><jsp:getProperty name="SendMail" property="ccAdd" /></td>
 </tr><tr>
  <th align="right" valign="top">Bcc:</th>
  <td><jsp:getProperty name="SendMail" property="bccAdd" /></td>
 </tr><tr>
  <th align="right">送信者:</th>
  <td><jsp:getProperty name="SendMail" property="fromAdd" /></td>
 </tr><tr>
  <th align="right">件名:</th>
  <td><jsp:getProperty name="SendMail" property="subject" /></td>
 </tr><tr>
  <th align="right" valign="top">本文:</th>
  <td><pre><jsp:getProperty name="SendMail" property="body" /></pre></td>
 </tr>
</table>

 <jsp:getProperty>要素は指定されたオブジェクトの指定されたプロパティ値を引用し、クライアント(ブラウザ)に返します。<jsp:getProperty>要素の一般的な構文は以下のとおりです。

<jsp:getProperty name="オブジェクト名" property="プロパティ名" />

 name属性のオブジェクト名は、<jsp:useBean>要素のid属性と対応する必要があります。property属性には、JavaBeansクラスの対応するプロパティ名を指定します。これによって、内部的にはJavaBeansクラスの対応するgetterメソッドが呼び出されるというわけです。

 例えば、

<td><jsp:getProperty name="SendMail" property="toAdd" /></td>

は、内部的には

<td><%=SendMail.getToAdd()%></td>

とまったく等価です。アクションタグのこのような挙動が可能になるのも、JavaBeansクラスが「必ずプロパティ名に対応するアクセサメソッドを持つ」というルールに基づいて記述されているおかげであるといってよいでしょう。

 ちなみに、本稿では登場しませんでしたが、JavaBeansクラスのプロパティに値を設定する場合には、<jsp:setProperty>要素を利用可能です。<jsp:setProperty>要素の一般的な構文は、以下のとおりです。

<jsp:setProperty
name="オブジェクト名"
property="プロパティ名"
[value="プロパティ値"|param="パラメータ名"] />

 value属性はプロパティ値を固定値として設定したい場合に、param属性はリクエストパラメータから設定したい場合に、それぞれ使用します。具体的な例を、対応するスクリプトレット構文と併記してみることにしましょう。

<% SendMail.setSmtp("smtp.xxxx.ne.jp"); %>

 というスクリプトレット構文は、次の<jsp.setProperty>構文で置き換えられます。

<jsp:setProperty name="SendMail" property="smtp" value="smtp.xxxx.ne.jp" />

 もう1例を紹介すると、次のようなスクリプトレット構文は、

<jsp:setProperty name="SendMail" property="toAdd" param="toAdd" />

 次のような<jsp.serProperty>構文で置き換えられます。

<% SendMail.setSmtp(request.getParameter("toAdd")); %>

 param属性が省略された場合には、property属性と等しい名前を持つリクエストパラメータが対応するプロパティにセットされます。また、property属性に"*"を設定した場合には、対応するJavaBeansクラスに属する「全」プロパティに対応するリクエストパラメータの値が自動的に設定されます。JavaBeansクラスの全プロパティをリクエストパラメータで設定したい場合などに便利でしょう。

<jsp:setProperty name="SendMail" property="*" />

One Point

JavaBeansクラス配下のプロパティにアクセスするには、<jsp:getProperty>、<jsp:setProperty>要素を使用します。


注:本稿では、入力された値をそのままブラウザに出力していますが、パラメータに悪意あるJavaScriptのコードなどが渡された場合、セキュリティホールの原因となる可能性があります(クロスサイトスクリプティング)。実運用のアプリケーションにおいては、入力値をあらかじめ検証する、または出力時にHTMLの予約文字を取り除くなどの処理を介する必要があります。クロスサイトスクリプティング)。実運用のアプリケーションにおいては、入力値をあらかじめ検証する、または出力時にHTMLの予約文字を取り除くなどの処理を介する必要があります。

 いかがでしたか? JavaBeansクラスを共有する場合に重要なスコープの概念、<jsp:useBean><jsp:setProperty>要素をはじめとしたアクションタグの役割、そして、JavaBeansクラスを利用することの効果が、これでご理解いただけたでしょうか。繰り返しではありますが、JavaBeansクラスを利用することで、以下のような効果が期待できます。

  • Model、View、Controlの役割分担が明確となる
  • その結果、アプリケーションの変更時にも影響個所が局所化できる
  • サーブレットクラスからは煩雑なビジネスロジックを、JSPファイルからはスクリプトレットをそれぞれ排除することが可能となるので、コードの可読性が向上する

 本稿では、構文的な規則以上に、JavaBeansクラスを利用することの効果、意味合いを実感することが大切です。その実感こそが、次に自らアプリケーションを設計する際にきっと思考の出発点になることでしょう。本稿が、アプリケーションの生産性・保守性を考える、1つのきっかけになれば幸いです。

 さて、長いようで短かった本連載も今回が最終回です。もちろん、JSP&サーブレットにはまだまだ注目すべき機能は少なくありません。フィルタやリスナクラス、カスタムタグ、そして、JSP 2.0で新たに導入されたタグファイル、式言語等々……本稿で紹介し切れなかったトピックスについては、拙著「スーパーリファレンス JSP&サーブレット」や「今日からつかえるJSP&サーブレットサンプル集」などを参考にしていただければ幸いです。

前のページへ 1|2       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。