13. フラグメント
2006.06.30 株式会社四次元データ 宮澤了祐
- 13.1. フラグメント
- 13.2. 属性値へのフラグメントの使用
13.1. フラグメント
JSP2.0より「フラグメント」という概念が取り込まれました。 フラグメントとはその名の通りJSPソースの断片を意味します。 具体的にはjavax.servlet.jsp.tagext.JspFragmentのインスタンスです。
特徴として、JspFragmentのinvoke()メソッドを呼び出した際にJspコードの評価を行うという特徴があります。 ただし
SimpleTagのボディ部は、実行時にJspFragmentオブジェクトとして取得されますが、「body-content」属性によって動作が違います。
「body-content」属性がscriptlessであれば、ボディ部のJSPコードを実行します。 「body-content」の属性にtagdependentを指定していた場合、 ボディ部が有効なJSPコードを含んでいたとしても解釈されることはありません。 invoke()メソッドが呼ばれた際にテキストそのままの形で出力されます。
また、SimpleTagのボディ部にスクリプトレットを記述することは出来ません。
例えばボディ部に以下の様なコードが記述されていた場合、
<myTag:hoge> ${1+2} </myTag:hoge>
「scriptless」を指定していれば「3」と、「tagdependent」を指定していれば「${1+2}」とテキストそのままの形で出力されます。
invoke()メソッドが呼ばれた際に、初めてJSPコードとして解釈されることを解説するために、 次のようなカスタムタグを作成します。
まず message というプロパティを持つBeanを作成します。
SampleBean.java
public class SampleBean{ String message; public void setMessage(String str){ message = str; } public String getMessage(){ return message; } }
次にFragmentTestを呼びだすJSPを作成します。
sample.jsp
<%@ page contentType="text/html; charset=euc-jp" import="SampleBean" %> <%@ taglib uri="http://www.TechScore.com/FragmentTest" prefix="myTag" %> <% SampleBean obj = new SampleBean(); obj.setMessage("スクリプトで設定"); request.setAttribute("result", obj); %> <jsp:useBean id="result" class="SampleBean"/> <p> <jsp:getProperty name="result" property="message" /> </p> <myTag:FragmentTest> <jsp:getProperty name="result" property="message" /> </myTag:FragmentTest>
<jsp:getProperty>はBeanの指定したプロパティを出力するアクションタグです。
次のようにタグを定義します。
<tag> <name>FragmentTest</name> <tag-class>FragmentTest</tag-class> <body-content>scriptless</body-content> </tag>
続いてFragmentTestのタグクラスを作成します。中心部分以外を省略します。
public class FragmentTest implements SimpleTag { ... private JspFragment body; public void setJspBody(JspFragment body) { this.body = body; } public void doTag() throws JspException, IOException { SampleBean bean = new SampleBean(); bean.setMessage("ボディ部で設定"); context.setAttribute("result",bean); body.invoke(context.getOut()); } ... }
これは次のように出力されます。
スクリプトで設定 ボディ部で設定
まず最初の<jsp:getProperty>で、スコープに登録されているオブジェクトのmessageプロパティが出力されます。 resultという名前のオブジェクトのmessageプロパティには「スクリプトで設定」という文字列が保存されています。
次にFragmentTestのdoTag()メソッドが呼びだされます。
message.invoke()が呼ばれた時点で、初めてボディ部の<jsp:getProperty/>が解釈され、 次のようなjavaコードに変換され、実行されます。 (簡易的に表記しただけなので、実際のコードとは違います。)
out.write(((SampleBean)context.findAttribute("result")).getMessage());
ここで初めてスコープに登録されているオブジェクトを調べるので、 新たに登録された「ボディ部で設定」という文字列をmessageプロパティに持つ、 SampleBeanオブジェクトが参照され、出力されます。
13.2. 属性値へのフラグメントの使用
JSP2.0より新たに属性を指定するアクションタグが追加されました
<jsp:attribute name="属性名"> ここにJSPコードを記述します。 ただしスクリプトレットは使用出来ません。 </jsp:attribute>
<Jsp:attribute>タグはnameで記述した属性に、Body部で設定した値を送るアクションタグです。 これを使用することで、属性値をフラグメントとしてカスタムタグに送ることが出来ます。
フラグメントとして受け取るためには、タグ定義ファイルの<attribute>の<fragment>をtrueに設定されます。 属性の型は自動的にjavax.servlet.jsp.tagext.JspFragmentになり、ほかの値を指定しても無視されます。
<tag> <name>MySimpleTag4</name> <tag-class>sample.MySimpleTag4</tag-class> <body-content>scriptless</body-content> <attribute> <name>message</name> <required>true</required> <fragment>true</fragment> </attribute> </tag>
<myTag:MySimpleTag4> <jsp:attribute name="message"> 属性値がフラグメントとして渡されています。 </jsp:attribute> </myTag:MySimpleTag4>
続いてカスタムタグクラスです。SimpleTagを用いて作成しましたが、他のTagインターフェイスを用いても同様にJspFragmentで受け取ることが出来ます。
public class MySimpleTag4 implements SimpleTag { ... private JspFragment message; public void setMessage(JspFragment str){ this.message = str; } public void doTag() throws JspException, IOException { message.invoke(context.getOut()); } ... }
JspFragment型の属性messageを受け取るsetMessage()メソッドにより属性を受け取っています。 JspFragmentのinvoke()メソッドを実行することで属性値が実行され、次のように出力されます。
属性値がフラグメントとして渡されています。