585x●JSB-BeansのMVアーキテクチャ
JSPからクラスファイル(Bean)を呼び出す方法には、拡張タグを使う方法とJavaのコードを使う方法の2種類の方法があります。
ここでは、新しくJSPから拡張タグを使って直接JavaBeansのインスタンスを使用する方法を学びます。
この時のJavaBeansは以下の条件で実装されていることが必要です。
【JSPから利用するためのJavaBeansの条件】
JSPから拡張タグを使って直接Beanを呼び出す場合、Beanは完全に標準的なJavaのクラスの考え方に従って作成されていなければなりません。
つまり以下のBeanの約束事が非常に重要です。
『Beanは引数無しのデフォルトコンストラクタを使ってインスタンス化し、Setterメソッドで値を設定して業務ロジックのメソッドを起動し、結果をgetterメソッドで受け取る
この時privateで宣言されたクラス変数をプロパティと呼び、set〇〇〇 get〇〇〇の〇〇〇はプロパティと名前が一致しなければいけない。
(ただし〇〇〇の最初の一文字は大文字になる)』
useBeanタグとスクリプティング変数
BeanをJSP内で実体化する<jsp:useBean>タグの使い方について説明します。
以下のJSPページは、同タグの利用例です。
<%@ page contentType="text/html; charset=UTF-8" %>
<jsp:useBean id="now" class="java.util.Date" /><html>
<head>
<title>JSPサンプル</title>
</head>
<body>
こんにちは、今の日時は <%= now %> です。
</body></html>
この<jsp:useBean>タグは、以下のような機能を提供します。
ここでいう「スクリプティング変数(scripting variable)」とは、JSPのスクリプトレットや標準アクション、EL(Expression Language)式にて読み書きできる変数です。Java言語の参照型変数と似ていますが、スクリプティング変数はあくまでJSP固有の機能であることに注意してください。
上記のコード例では、まず、id属性で指定したスクリプティング変数「now」がスコープ内(これについては、後述します)で作成済みかどうか調べます。作成済みでない場合は、class属性で指定した「Date」クラスのオブジェクトを1つ生成し、now変数にセットします。その後、JSPページの後半にある「<%= now %>」というスクリプトレットにより、now変数にセットされたDateオブジェクトを文字列に変換したもの、すなわち現在の日時がブラウザに表示される仕組みです。DateクラスはBean対応で実装されています。
これは、以下のjavaのコードと同じ意味ですので、実装して確認してみてください。
date.jsp
4行目から11行目は必要ありません
16行目以降は以下のように書き換え可能です
<jsp:getProperty name="now" property="year" />
<jsp:getProperty name="now" property="month" />
<jsp:getProperty name="now" property="date" />
<jsp:getProperty name="now" property="hours" />
<jsp:getProperty name="now" property="minutes" />
<jsp:getProperty name="now" property="seconds" />
</body>
</html>
スクリプティング変数の「スコープ」を理解する
さて、上述のコード例では省略していましたが、useBeanタグでは「scope属性」を指定できます。
<jsp:useBean id="now" class="java.util.Date" scope="request"/>
このscope属性は、id属性で指定したスクリプティング変数の「スコープ」を指定します。このスコープとは、「変数の有効範囲」を表すもので、以下の4種類のスコープのいずれかを指定できます。ちなみに、先ほどのコード例のようにscope属性を省略した場合は、デフォルトのpageスコープが選択されます。
以下、各スコープの意味と使い方について説明します。
pageスコープはローカル変数と同じ
pageスコープとは、「スクリプティング変数の有効範囲がJSPページ内である」ことを意味します。
例えば、先ほどのコード例において、useBeanタグによって作成されたnow変数は、同じJSPページ内にあるスクリプトレット「<%= now %>」にて参照できますが、同ページの外(例えば、ほかのJSPページ)から参照できません。
pageスコープのスクリプティング変数は、それが作成されたJSPページの処理が終わると有効範囲外となり、メモリから削除されます。
例えば、上記コード例をWebブラウザで表示した後、リロードボタンをクリックしてみると、クリックするたびに日時が更新されることが分かります。つまり、JSPページの処理が繰り返されるごとにnow変数が作り直されているのです。
これはちょうど、Javaのローカル変数と同様の振る舞いです。よって、pageスコープのスクリプティング変数は、ローカル変数的な目的(JSPページ内での処理結果を一時的に保持するなど)に使用します。
requestスコープはMVCをまたに掛ける
requestスコープは、「スクリプティング変数の有効範囲がHTTPリクエスト内である」ことを表します。つまり、下記のような一連の処理が、requestスコープのスクリプティング変数の有効範囲となります。
Webブラウザから届いたHTTPリクエストをWebコンテナが受信する
WebコンテナがJSPやサーブレットを呼び出し、HTTPリクエストを処理する
処理結果のHTTPレスポンスをWebブラウザに送信する
HTTPリクエストの処理が1枚のJSPページだけで済んでしまう場合は、requestスコープとpageスコープに違いはありません。しかし、以下のようなケースではrequestスコープが意味を持ちます。
requestスコープのスクリプティング変数が最もよく用いられるケースは、MVCモデルを構成する場合です。
MVCモデルでは、HTTPリクエストを、まずサーブレット(コントローラ)で受け付け、JavaBeans(モデル)でビジネス・ロジックを実行したのち、その結果をJSPページ(ビュー)で表示する、という流れで実行が進みます。このとき、サーブレットやJavaBeansからJSPページへ処理結果を渡す手段として、requestスコープのスクリプティング変数が利用されます。
sessionスコープはPCごと
sessionスコープとは、「スクリプティング変数の有効範囲がHTTPセッション内である」ことを意味します。
ここでいう「HTTPセッション」とは、クライアントごとに用意されるオブジェクトのことです。よって、sessionスコープのスクリプティング変数を利用することで、クライアントごとに異なる状態を保持できます。
sessionスコープは、例えば、ショッピングカード内容を保存したり、各ユーザーのログイン/ログアウト状態を記録したりするなど、いわゆるセッション情報を保持するために利用します。
例えば、冒頭のコード例のuseBeanタグに「scope="session"」という記述を追加してみます。この状態でWebブラウザからJSPページを開き、リロードボタンをクリックします。すると、pageスコープのときとは違い、日時が更新されないことが分かります。なぜなら、useBeanタグによって作成されたnow変数がHTTPセッションに保存されるため、同じクライアントからの2回目以降のアクセスでは、HTTPセッションに保存された既存のnow変数をそのまま再利用するからです。
また、続いてほかのPCのWebブラウザから同じJSPページを開いてみます。すると、先ほどとは異なる日時が表示されます。これはつまり、クライアントを識別して、それぞれに別々のnow変数を作成しているからです。
なお、sessionスコープのスクリプティング変数は、Webブラウザからのアクセスが一定時間以上(Tomcatのデフォルトでは、15分)途切れると、HTTPセッションとともに破棄されます。
applicationスコープはみんなのもの
applicationスコープとは、「スクリプティング変数の有効範囲がWebアプリケーション内である」ことを表します。つまり、Webアプリケーション全体で1つの変数を共有できることを意味します。
例えば、コード例のuseBeanタグに「scope="application"」という記述を追加します。この状態で、sessionスコープの例のように、複数のPCから同じJSPページにアクセスします。sessionスコープのときとは異なり、今度はPCの違いを識別せずに、両方とも同じ日時が表示されることが分かります。
こうした振る舞いから、applicationスコープは、Webアプリケーション全体で共有したいデータ、例えばマスターデータのキャッシュやアクセスカウント数などを保持する目的で利用できます。ちなみに、applicationスコープに保存された変数の値は、WebアプリケーションをWebコンテナからアンロード(削除)するまでメモリ上に存在し続けます。
以上、useBeanタグとスクリプティング変数の機能について説明しました。
JavaBeansのプロパティを取り出すgetPropertyタグ
JavaBeansの活用に欠かせない標準アクションである<jsp:getProperty>タグと<jsp:setProperty>タグの機能を解説します。
まずは、<jsp:getProperty>タグです。同タグは、JavaBeansのプロパティから値を読み出し、Webブラウザ上に文字列として表示します。以下の要領で記述します。
<jsp:getProperty name="<変数名>" property="<プロパティ名>" /> |
この場合、属性nameで指定したスクリプティング変数が指すJavaBeansについて、属性propertyで指定したプロパティの値を取得し、Webブラウザに表示します。
では、このタグの機能を実際にTomcat上で試してみましょう。最初に、対象となるJavaBeansクラスを以下のように作成します。
TestBean.java
このJavaBeansは、「userId」および「userName」という2つのプロパティを持ち、それぞれについてgetterメソッドとsetterメソッドを備えています。
次に、JavaBeansを利用するJSPページを作成しましょう。
test1.jsp
ここでは、冒頭の<jsp:useBean>タグでは、クラス名「jp.ict.aso.model.TestBean」で指定したJavaBeansのインスタンスを生成し、スクリプティング変数「user」にセットしています。なお、scope属性は未指定であるため、デフォルトのpageスコープが選択されます。
続いて、後半の<jsp:getProperty>タグでは、変数userにセットされたJavaBeansより、プロパティ「userId」の値を取得してWebブラウザに出力しています。
test1.jspを実行すると以下のような内容が表示されます。
このように、userIdプロパティおよびuserNameプロパティの初期値である「<未設定>」という文字列がそれぞれ表示されているのが分かります。
ちなみに、今回の例では、いずれのプロパティもString型ですので、setterメソッドが返す文字列がそのままWebブラウザに表示されます。
もし、プロパティがString型以外(例えば、Date型)であった場合、<jsp:getProperty>タグでは、戻り値のオブジェクトに対して「toStringメソッド」を呼び出し、オブジェクトを文字列に変換します。プリミティブ型の場合は、その値をそのまま文字列に変換します。
プロパティに値をセットするsetPropertyタグ
続いては、<jsp:setProperty>タグの使い方を紹介します。同タグは、JavaBeansのプロパティに値をセットする機能を備え、以下のように記述します。
<jsp:setProperty name="<変数名>" property="<プロパティ名>" value="<値>" /> |
この場合、属性nameと属性propertyで指定したJavaBeansのプロパティに対し、属性valueの値をセットします。
では、このタグの機能を実際にテストしてみましょう。
test2.jsp
ここで、<jsp:setProperty>タグでは、user変数が指すJavaBeansのプロパティuserIdに対し、「001」という文字列をセットしています。その後の<jsp:getProperty>タグによって、セットした値をWebブラウザに表示します。
test2.jspを実行すると以下のような内容が表示されます。
パラメータをそのままプロパティにセットすることも可能
<jsp:setProperty>タグでは、以下のような書き方も可能です。
<jsp:setProperty name="<変数名>" property="<プロパティ名>" param="<パラメータ名>" /> |
この書き方では、Webブラウザから受信したパラメータのうち、属性paramで指定されたものの値を取得し、それをJavaBeansのプロパティにセットします。
よって、例えば、HTMLフォームで入力されたデータをJavaBeansにそのまま渡す場合に利用できます。なお、指定したパラメータがWebブラウザから送信されていない場合は、プロパティの値は変化しません(つまり、未入力は検出できないので、注意が必要です)。
また、以下のような書き方もできます。
<jsp:setProperty name="<変数名>" property="*" /> |
この場合、パラメータ名とプロパティ名が一致したものすべてについて、パラメータからプロパティへと値をセットします。
例えば、HTMLフォーム上に「userId」というパラメータを定義し、一方で同じ名前のプロパティをJavaBeansに持たせておくことで、上記のコードによってHTMLフォームの入力データをJavaBeansで受け取れます。
では、この使い方を実際に試してみましょう。
test3.jsp
ここで中ほどのHTMLフォームにおいて、JavaBeansのプロパティ名と同じ名前のパラメータを配している点に注意してください。これにより、続く<jsp:setProperty>タグにて、HTMLフォームの入力データをまとめてJavaBeansに渡せます(ちなみに、コード中ほどのsetCharacterEncodingメソッドは、文字化けを防ぐための記述です。
test3.jspを実行すると以下のような内容が表示されます。
※うまく動きますか?test3.jspファイルの内容には誤りがありますよ。エラーや文字化けまた字下げの誤り等があれば対処してください。
日本語が表示できたらスクショを提出してください
以上、<jsp:useBean>タグと<jsp:getProperty>タグと<jsp:setProperty>タグの使い方について説明しました。