目次へ

13. フラグメント

2006.06.30 株式会社四次元データ 宮澤了祐

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()メソッドを実行することで属性値が実行され、次のように出力されます。

属性値がフラグメントとして渡されています。

↑このページの先頭へ

こちらもチェック!

PR
  • XMLDB.jp