さて、最後にリクエスト属性に保存されたJavaBeansクラスを、今度は「.jsp」ファイルで再び「復元」する必要があります。
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 |
さて、ここで初めて「スコープ」というキーワードが登場しました。スコープ(Scope)とは、読んでその名のとおり「変数が保持される期間・範囲」を表しますが、このスコープという概念は、複数のクラス(サーブレット・JSP)間でJavaBeansクラスを共有する場合に大変重要なものです。
JSP&サーブレットコンテナ(Tomcat)は、JavaBeansクラスをインスタンス化するに際して、以下のような手順を踏みます。
id属性とscope属性が同一のオブジェクトが存在するか? |
つまり、JavaBeansクラスが同一であるかの判断は「オブジェクト名」ではなく、「オブジェクト名+スコープ」で行われるということです。いくらほかのサーブレットクラス・JSPファイルでJavaBeansクラスを保持していたとしても、スコープが一致していないJavaBeansクラスは共有することができませんので、注意してください。
ちなみに、scope属性で指定可能な設定値は、以下のとおりです。
スコープ名 | 概要 |
---|---|
page | 現在のページ(ファイル)内でのみ有効。ほかのページと共有の必要がない単発的な処理を行う場合に使用する。全スコープ中で最も有効範囲の狭い設定(デフォルト) |
request | 一連のリクエスト処理の範囲で有効。現在のページ、およびフォワード(またはインクルード)された先のページでのみ、値を共有することができる |
session | ユーザーセッションの範囲で有効。複数の独立したファイル(クラス)間で情報を共有したい場合に使用する(例:ECサイトにおける買い物カゴなど)。異なるユーザーとの間では情報は共有されない |
application | 現在のアプリケーション内のすべてのファイル(クラス)間、アプリケーションにアクセスしている全ユーザー間で有効。全スコープ中で最も有効範囲の広い設定 |
表 scope属性に設定可能な値 |
それぞれのスコープの違いを図示すると以下のようになります。
より有効範囲の広いスコープを採用すれば、それだけ広範囲でデータを共有することができますが、基本的にスコープは必要最小限の範囲にとどめることが重要です。というのも、不必要に広範囲なスコープを設定することで、以下のような問題が発生する可能性があるためです。
特に、application・sessionスコープは、分・時間単位で保持される可能性もあるため(page・requestスコープは、一般的にミリ秒・秒単位で破棄されます)、本当にそのスコープが必要なのかどうか、使用に際しては十分な検討が必要でしょう。
「.jsp」ファイルでJavaBeansクラスをインスタンス化するには、<jsp:useBean>要素を使用します。<jsp:useBean>要素は、id・scope属性が一致するJavaBeansクラスがすでに存在する場合、既存のオブジェクトをそのまま再利用します。
さて、サーブレットクラスで保持しておいたJavaBeansクラスが無事に復元できたところで、今度はJavaBeansクラス内のプロパティにアクセスしてみましょう。
result.jspの以下部分に注目してみてください。
<table border="1"> |
<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 |
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="*" /> |
JavaBeansクラス配下のプロパティにアクセスするには、<jsp:getProperty>、<jsp:setProperty>要素を使用します。
注:本稿では、入力された値をそのままブラウザに出力していますが、パラメータに悪意あるJavaScriptのコードなどが渡された場合、セキュリティホールの原因となる可能性があります(クロスサイトスクリプティング)。実運用のアプリケーションにおいては、入力値をあらかじめ検証する、または出力時にHTMLの予約文字を取り除くなどの処理を介する必要があります。クロスサイトスクリプティング)。実運用のアプリケーションにおいては、入力値をあらかじめ検証する、または出力時にHTMLの予約文字を取り除くなどの処理を介する必要があります。
いかがでしたか? JavaBeansクラスを共有する場合に重要なスコープの概念、<jsp:useBean><jsp:setProperty>要素をはじめとしたアクションタグの役割、そして、JavaBeansクラスを利用することの効果が、これでご理解いただけたでしょうか。繰り返しではありますが、JavaBeansクラスを利用することで、以下のような効果が期待できます。
本稿では、構文的な規則以上に、JavaBeansクラスを利用することの効果、意味合いを実感することが大切です。その実感こそが、次に自らアプリケーションを設計する際にきっと思考の出発点になることでしょう。本稿が、アプリケーションの生産性・保守性を考える、1つのきっかけになれば幸いです。
さて、長いようで短かった本連載も今回が最終回です。もちろん、JSP&サーブレットにはまだまだ注目すべき機能は少なくありません。フィルタやリスナクラス、カスタムタグ、そして、JSP 2.0で新たに導入されたタグファイル、式言語等々……本稿で紹介し切れなかったトピックスについては、拙著「スーパーリファレンス JSP&サーブレット」や「今日からつかえるJSP&サーブレットサンプル集」などを参考にしていただければ幸いです。
Copyright © ITmedia, Inc. All Rights Reserved.