@IT|@IT自分戦略研究所|QA@IT|イベントカレンダー+ログ | ||
Loading
|
@IT > Webアプリケーション構築の最適解 > JSPカスタムタグ徹底入門(1) |
|
|
|
Webアプリケーション構築の最適解“JSPカスタムタグとは?” ■カスタムタグ登場の背景 J2EEアプリケーションの生産性を高め、メンテナンスや拡張を容易にするためには、機能や役割に基づいてうまく「部品化」(コンポーネント化、モジュール化)を行い、コンポーネントの再利用性や移植性を高めていく必要があります。改めて言うまでもなく、ビジネスロジック層でのコンポーネントとしては、Enterprise JavaBeans(EJB)が用意されています。 それでは、プレゼンテーション層ではどうでしょうか? サーブレットやJSPをWebモジュール(Webアプリケーション)としてモジュール化することはできますが、これが再利用性の高い「コンポーネント」だと考える人は、いないでしょう。 ここで、J2EEによるWebアプリケーション開発の現状を考えてみましょう。EJBを使うにせよ使わないにせよ、そして、J2EEアプリケーションモデルのMVCアーキテクチャを採用するにせよしないにせよ、ほとんどの場合、クライアントへのレスポンスの生成(MVCアーキテクチャの「ビュー」)には、JSPを利用していることでしょう。 思いつくままにJSPページを開発していくと、条件分岐やループ、処理フローの制御、データベースアクセスなどを実現するために、おそらく(“<%と“%>””に囲まれたJavaコードである)スクリプトレットを多用してしまうことでしょう。この場合、同じようなJavaコードを、多数のJSPページのあちらこちらに繰り返し書くことになってしまいます。また、JSPページのデザインをWebデザイナに任せる場合には、JSPやJavaのシンタックスを理解し開発することを、彼らに求めるのは酷でしょう。 JSPでは、<jsp:useBean>を用いて「再利用可能なコンポーネント」と言われるJavaBeansを使えるのでは、と思うかもしれません。ですが、サーバサイドにおけるJavaBeansは、データ中心のコンポーネントとしては使いやすいものの、それ以外の用途にはあまり向いていないでしょう。<jsp:setProperty>および<jsp:setProperty>を用いて、データの設定と取得は簡単に行えます。MVCアーキテクチャのコントローラとビューの間や、HTTPセッション内で、データを受け渡したり共有したりする場合には、JavaBeansは非常に便利でしょう(<jsp:useBean>のscope属性の値には、page、request、session、またはapplicationを指定できたことを思い出してください)。 それでは、上で述べたようなスクリプトレットの問題を回避するためには、どうしたらよいのでしょうか? まさに、この問題の解決策が、カスタムタグのメカニズムなのです。 ■カスタムタグとは? JSPでは、<jsp:useBean>や<jsp:include>、<jsp:forward>などのアクションが、標準のアクションとして定義されています。カスタムタグとは、JSPページ内で利用可能なカスタムのアクションを定義するものです。関連する一連のカスタムタグは、後述するタグハンドラ(TLD)というファイルを用いてタグライブラリとして定義されます。 カスタムタグは、名前空間接頭辞を持つXMLの要素と同様のシンタックスを採用しています。単純なアクションは、次のように空要素で指定できます。
より複雑なアクションは、次のように、空でない要素として指定できます。要素の内容(開始タグと終了タグとの間)は、ボディ(本体)と呼ばれます。ボディには、通常のJSPページのフラグメントを含めることができ、ほかのカスタムタグをネストさせることも可能です。
カスタムタグ開発者は、カスタムタグが提供する機能の実装に集中します(ビジネスロジックを実装する開発者が、これを兼ねる場合が多いかもしれません)。JSP開発者(Webデザイナ)は、大量のスクリプトレットを書くことなく、カスタムタグの仕様(機能、要素名、属性名とその値の意味など)のみを理解しておけば、ページデザインを進められます。つまり、明確に役割の分担ができるわけです。 タグライブラリには、大きく分けて、次の4種類があります。
(1)JSPコンテナベンダ(アプリケーションサーバベンダ)が提供するタグライブラリ タグライブラリはポータブル(移植可能)ですので、任意のJSPコンテナで動作するはずです。が、アプリケーションサーバベンダは、自社のJSPコンテナ以外での動作はサポートしないでしょう。 (2)オープンソースの、あるいはサードパーティが提供するタグライブラリ また、当コーナーで近日公開予定の「JSPカスタムタグ・ディレクトリ」にも、多数のタグライブラリへの情報をまとめる予定です。 (3)JSP Standard Tag Library(JSTL) 現在、JSR-052において、このような共通した機能を持つタグライブラリ「JSP Standard Tag Library (JSTL)」の標準化作業が進行中です。なお、JSTLのリファレンス実装は、Jakarta Projectが行っています。 (4)独自に開発したタグライブラリ 例えば、J2EE BruePrintsのサンプルアプリケーション「Java Pet Store」でも、タグライブラリが多用されています。 ■JSPカスタムタグの仕組み ここでは、簡単なサンプルコードを使って、カスタムタグのアーキテクチャを説明していきましょう。カスタムタグの開発者が作成するのは、個別のカスタムタグの機能を実装したタグハンドラ、そして、カスタムタグの構成情報を指定するタグライブラリディスクリプタ(TLD)です。 例として、「こんにちは」と出力するだけの単純なカスタムタグを実装することにしましょう。 ■タグライブラリディスクリプタ(TLD) タグハンドラのソースコードは、以下のようになります。
ここで、タグハンドラに関連するインターフェイスやクラスを説明しておきましょう。カスタムタグに関連するインターフェイスやクラスは、javax.servlet.jsp.tagextパッケージに含まれています。 タグハンドラは、Tagインターフェイス、またはBodyTagインターフェイスのいずれかをimplementsする必要があります。タグがボディを持たない場合や、ボディを持ち、ボディを操作しない(ボディを、JSPの一部としてそのままインクルードする)場合、タグハンドラは、Tagインターフェイスをimplementsします。タグがボディを持ち、ボディを操作する場合には、タグハンドラは、BodyTagインターフェイスをimplementsします。
実際には、これら2つのインターフェイスのベース実装クラスとして、TagSupportクラスとBodyTagSupportクラスが用意されていますので、タグハンドラは、これらをextendsして、いくつかのメソッドをオーバライドするケースが、ほとんどでしょう。以下のクラス図は、タグハンドラに関連するインターフェイスやクラスの間の関係を示しています。
JSP 1.1でのjavax.servlet.jsp.tagextパッケージのJavaDocも、参照してください。また、Ja-Jakartaプロジェクトは、JSP 1.2のJavaDocを翻訳していますので、こちらも参照してください。 TagSupportクラスのメソッドの中で、開発者がしばしばオーバライドするものは、開始タグを処理するdoStartTag()メソッド、および終了タグを処理するdoEndTag()メソッドです。サンプルコードでも、この2つのメソッドをオーバライドしていますね。 このサンプルでは登場しませんが、カスタムタグが属性をもつ場合には、その属性値を設定・取得するsetter/getterメソッドも必要です。例えば、カスタムタグがname属性をもつ場合には、setName()とgetName()メソッドを実装します。実は、タグハンドラは、属性をプロパティとしてもつJavaBeansなのです。 さて、サンプルコードでdoStartTag()メソッドやdoEndTag()メソッドの戻り値、SKIP_BODYやEVAL_PAGEは、何を意味するのでしょうか? これらの戻り値は、その後の処理を指定するために使われるものです。
JSPページをシリアルに評価していくステップで、これらの戻り値が、その後の処理を決定するために使われることが分かるでしょう。 次の図は、TagSupportクラスをextendsしたカスタムタグの、典型的なシーケンス図です。 サンプルコードでは、doStartTag()メソッドで「こんにちは」を出力してからSKIP_BODYを返し、doEndTag()メソッドでは単にEVAL_PAGEを返しています(TagSupportクラスのdoEndTag()メソッドは、単にEVAL_PAGEを返すものなので、サンプルコードのdoEndTag()メソッドはなくても構いません)。 今回のサンプルのように、ボディをもたないタグの場合、doStartTag()メソッドでは単にSKIP_BODYを返し、doEndTag()メソッドで「こんにちは」を出力してからEVAL_PAGEを返すようにしても、結果はまったく同じになることが分かるでしょう(TagSupportクラスのdoStartTag()メソッドは、単にSKIP_BODYを返すものなので、この場合はdoStartTag()メソッドはなくても構いません)。 サンプルコードでは、TagSupportクラスのpageContextフィールドを用いて、カレントのJspWriterを取得し、そこに「こんにちは」を出力しています。
setPageContext()メソッドによって設定されるpageContextフィールドは、javax.servlet.jsp.PageContextクラスのインスタンスです。PageContextクラスのgetRequest()、getResponse()、getSession()、getServletContext()などのメソッドを利用することにより、セッション情報へのアクセスや、HTTPレスポンスヘッダの操作など、さまざまな情報にアクセスしそれらを操作することが可能となります。 ■タグライブラリディスクリプタ (TLD) タグハンドラを実装しただけでは、まだカスタムタグとして使うことはできません。タグライブラリディスクリプタ(TLD)と呼ばれるXML文書を作成する必要があります。TLDは、その名の通り(1つ以上のカスタムタグである) タグライブラリの構成情報を記述するものです。今回は、次のようなTLDファイルmytaglib.tldを作成します。
<taglib>要素は、タグライブラリ全体の構成情報を表す要素と、1つ以上の<tag>要素を子要素としてもちます。
<tag>要素は、各カスタムタグの構成情報を表す要素を子要素としてもちます。
カスタムタグが属性を持つ場合、<tag>要素には、各属性ごとに<attribute>子要素を指定します。詳細は、次のURLで取得できるDTDや、JSP仕様などを参照してください。 http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd タグハンドラとTLDができれば、カスタムタグは完成です。では、カスタムタグを使うには、どうすればいいのでしょうか? タグハンドラも、Webモジュールが使用するクラスですから、WebモジュールのWEB-INF/classes以下にクラスファイルとして配置する、またはJARファイルとしてWEB-INF/lib以下に配置する必要があります。今回は、タグハンドラHelloTag.classを次の位置に配置します。 WEB-INF/classes/mytaglib/HelloTag.class TLDは、通常、WEB-INF/以下に配置します。 WEB-INF/mytaglib.tld そして、Webモジュールのデプロイメントディスクリプタ WEB-INF/web.xmlに<taglib>要素を追加します。
URIは、タグライブラリを識別するためだけに使われますので、有効なURLである必要はありません。 JSPページでは、taglibディレクティブを用いて、利用するタグライブラリのURIを接頭辞にバインドします。次の例では、mytaglibという接頭辞を指定しています。
簡単なサンプルコードを用いて、タグハンドラの実装、TLDの作成、デプロイメントディスクリプタの設定、JSPページのカスタムタグの利用を、一連の流れに沿って見てきました。 本稿では、カスタムタグの極めて基本的な部分しか説明していません。もし、カスタムタグに興味を持たれたならば、Webページや書籍などでより詳しい情報を集めることをお勧めします。
|
|