Section10: カスタムタグライブラリの構築
タグハンドラ
要素 | 多重度 | 説明 |
---|---|---|
taglib | 1 | ルート要素 |
tlib-version | 1 | カスタムタグのバージョン |
short-name | 1 | カスタムタグの略称 |
uri | ? | このタグライブラリに設定するURI。taglibディレクティブのuri属性で指定される。 |
tag | * | タグに関する設定。 |
name | 1 | タグの名前。 |
tag-class | 1 | タグハンドラクラスの完全修飾名。 |
tei-class | ? | タグの検証を行うTagExtraInfoを継承したクラスの完全修飾名。タグの属性の組み合わせや、属性の値に制約を設ける場合などに使用する。 |
body-content | 1 | ボディ部のタイプを指定。JSP, scriptless, empty, tagdependentのいずれかを指定する。 |
valiable | * | スクリプティング変数に関する設定。 |
name-given | name-from-attribute | 1 | name-given: スクリプティング変数の名前を固定的に指定。 name-from-attribute: スクリプティング変数の名前を、カスタムタグの属性の値で指定する場合に使用。属性名を指定する。 |
variable-class | ? | スクリプティング変数の型の完全修飾名。省略時のデフォルトはjava.lang.String。 |
declare | ? | スクリプティング変数を新たに定義するかどうかをtrueまたはfalseで指定。すでに定義されている変数を使う場合はfalseを指定する。省略時のデフォルトはtrue。 |
scope | ? | スクリプティング変数の有効範囲を以下の3つから指定。 AT_BEGIN: 開始タグ以降で有効。 AT_END: 終了タグ以降で有効。 NESTED: カスタムタグのボディ部内のみで有効。省略時のデフォルトはNESTED。 |
attribute | * | タグの属性に関する設定。 |
name | 1 | 属性名。 |
required | ? | 必須の属性かどうかをtrueまたはfalseで指定する。省略時のデフォルトはfalse。 |
rtexprvalue | ? | 属性に式が使用できるかどうかをtrueまたはfalseで指定。省略時はfalse。fragmentと同時使用不可。 |
type | ? | 属性値の型の完全修飾名。省略時はjava.lang.String。rtexprvalueとセットで使用する。 |
fragment | ? | 属性がJSPフラグメントかどうかをtrueまたはfalseで指定。省略時のデフォルトはfalse。JspFragment型を受け取るsetterを定義する必要がある。フラグメント内にはスクリプト要素を書くことはできない(EL式は評価される)。rtexprvalue, type, deferred-value, deferred-methodと同時使用不可。 |
deferred-value | ? | EL式の遅延評価に関する設定。fragment, deferred-methodと同時使用不可。 |
type | ? | 評価結果の型の完全修飾名。省略時のデフォルトはjava.lang.Object。 |
deferred-method | ? | EL式の遅延評価によるメソッド呼び出しの設定。fragment, deferred-valueと同時使用不可。 |
method-signature | ? | メソッドのシグネチャ。 |
dynamic-attributes | ? | 動的属性の使用するかどうかをtrueまたはfalseで指定。省略時のデフォルトはfalse。 |
function | * | EL式でstaticメソッド呼び出しを行うための設定。 |
name | 1 | Functionの名前。 |
function-class | 1 | メソッドが定義されたクラスの完全修飾名。 |
function-signature | 1 | メソッドのシグネチャ。引数や戻り値の型は完全修飾名を使用すること。 例: java.lang.String testFunc(java.lang.String, int) |
- 以下のタグおよびその子タグは省略した
- display-name
- icon
- description
- validator
- listener
- example
- tag-extension
- tag-file
- taglib-extension
- function-extension
種類 | 説明 | |
---|---|---|
クラシックタグハンドラ | JSP1.1から導入されているタグハンドラ。実装がやや煩雑だが、ボディにスクリプトレットまたは式を書く場合はこれを使う必要がある。 | |
シンプルタグハンドラ | JSP2.0から導入されたシンプルなタグハンドラ。ボディにはEL式を使用できるが、スクリプトレット、式は使用不可能。 | |
タグファイル | JSPまたはXMLを使用してカスタムタグを作成する。タグハンドラクラスは記述しない。 |
クラシックタグハンドラ
シグネチャ | 説明 | |
---|---|---|
public int doStartTag() | 開始タグの処理を行う。 | |
public int doEndTag() | 終了タグの処理を行う。 | |
public void release() | タグハンドラが解放状態に移る際に実行される。 | |
public void setPageContext(PageContext pc) | PageContextオブジェクトをセットする。タグ実行前に自動的に呼び出される。 | |
public void setParent(Tag t) | 親タグをセットする。タグ実行前に自動的に呼び出される。 | |
public Tag getParent() | 親タグを取得する。親タグがない場合はnull。 |
- Tagが継承しているJspTagインターフェースはマーカーインターフェースなのでメソッドはない。
定数を返却するメソッド | 定数 | 説明 | |
---|---|---|---|
doStartTag() | static int EVAL_BODY_INCLUDE | ボディ部を評価する。 | |
doStartTag() | static int SKIP_BODY | ボディ部をスキップする。 | |
doEndTag() | static int EVAL_PAGE | タグ以降のページを評価する。 | |
doEndTag() | static int SKIP_PAGE | タグ以降のページをスキップする。 |
シグネチャ | 説明 | |
---|---|---|
public int doAfterBody() | ボディ部の評価終了後に呼び出される。 |
定数を返却するメソッド | 定数 | 説明 | |
---|---|---|---|
doStartTag() | static int EVAL_BODY_INCLUDE | ボディ部を評価する。 | |
doStartTag() | static int SKIP_BODY | ボディ部をスキップする。 | |
doAfterBody() | static int EVAL_BODY_AGAIN | ボディ部を再度評価する。 | |
doAfterBody() | static int SKIP_BODY | ボディ部の評価を終了する。 | |
doEndTag() | static int EVAL_PAGE | タグ以降のページを評価する。 | |
doEndTag() | static int SKIP_PAGE | タグ以降のページをスキップする。 |
フィールド | 説明 | |
---|---|---|
protected String id | id属性の値を格納するためのフィールド。 | |
protected PageContext pageContext | PageContextを格納するためのフィールド。 |
- privateなフィールドといては以下が定義されている。privateなため、使用する場合はgetterから取得する。
- Tag parent
- Hashtable<java.lang.String,java.lang.Object> values
シグネチャ | 説明 | |
---|---|---|
public static Tag findAncestorWithClass(Tag from, Class klass) | 第1引数で指定されたタグから見て、第2引数で指定されたクラスに対応する先祖タグを検索する。複数候補がある場合は、タグから最も近いものが返される。該当するタグがない場合はnullを返す。 | |
public void setId(String id) | id属性をセットする。 | |
public String getId() | id属性を返す。セットされていない場合はnullを返す。 | |
public void setValue(String k, Object o) | keyにオブジェクトを関連づける。 | |
public Object getValue(String k) | keyに関連付けられたオブジェクトを取得する。 | |
public Enumeration<String> getValues() | setValue(String k)メソッドで関連付けられたkeyのEnumerationを返す。 | |
public void removeValue(String k) | keyに関連付けられたオブジェクトを削除する。 |
- getValues()が返すのはvalueではなくkeyのEnumerationなので注意。
- setPageContext, setParent, getParentのデフォルト実装も用意されているので、開発者が実装する必要はない。
- pageContextはフィールドから取得、parentはgetterを通じて取得する。
シグネチャ | 説明 | |
---|---|---|
public void doInitBody() | ボディ部での処理の初期化が必要な場合はこのメソッド内に記述する。ボディ部が初めて評価されるときに呼ばれる。 | |
public void setBodyContent(BodyContent b) | bodyContentをセットする。 |
- setBodyContent(b) → doInitBody() の順番で呼び出される。
定数を返却するメソッド | 定数 | 説明 | |
---|---|---|---|
doStartTag() | static int EVAL_BODY_BUFFERED | ボディ部をBodyContentを使って評価する。この定数が返されるときだけdoStartTagメソッドの後に、setBodyContentメソッド、doInitBodyメソッドがこの順番で呼ばれる。 | |
doStartTag() | static int EVAL_BODY_INCLUDE | ボディ部を評価する。 | |
doStartTag() | static int SKIP_BODY | ボディ部をスキップする。 | |
doAfterBody() | static int EVAL_BODY_AGAIN | ボディ部を再度評価する。 | |
doAfterBody() | static int SKIP_BODY | ボディ部の評価を終了する。 | |
doEndTag() | static int EVAL_PAGE | タグ以降のページを評価する。 | |
doEndTag() | static int SKIP_PAGE | タグ以降のページをスキップする。 |
シグネチャ | 説明 | |
---|---|---|
public void clearBody() | ボディをクリアする。 | |
public void flush() | 使用不可。呼び出すとIOExceptionが投げられる。 | |
public JspWriter getEnclosingWriter() | JspWriterを取得する。 | |
abstract public Reader getReader() | ボディ部を読み込むReaderを取得する。 | |
abstract String getString() | ボディ部の値をStringで取得する。 | |
abstract void writeOut(Writer out) | BodyContentの内容を指定されたWriterに書き出す。 |
- doAfterBody()内では、BodyContent#getEnclosingWriter()で取得したJspWriterに出力しないと画面に表示できない。
シンプルタグハンドラ
シグネチャ | 説明 | |
---|---|---|
public void doTag() | タグの処理を行う。 | |
public void setJspContext(JspContext pc) | JspContextオブジェクトを設定する。タグ実行前に自動的に呼び出される。 | |
public void setJspBody(JspFragment jspBody) | ボディ部をJSPフラグメントとして設定する。タグ実行前に自動的に呼び出される。 | |
public void setParent(JspTag parent) | 親タグを設定する。タグ実行前に自動的に呼び出される。 | |
public JspTag getParent() | 親タグを取得する。 |
- Tagインターフェースと違い、doTag()は定数を返さない。
- TagインターフェースのAPIと比べて、引数や戻り値がTagではなくJspTagとなっていることに注意。
- TagインターフェースのAPIと比べて、PageContextではなくJspContextとなっていることに注意。(JspContextはPageContextの親クラス)
- クラシックタグハンドラはタグのインスタンスが使いまわされる可能性があるが、SimpleTagは1回の使用でインスタンスを破棄する。そのため、後処理はdoTag()の最後に記述すればよいので、release()メソッドは定義されていない。
シグネチャ | 説明 | |
---|---|---|
public static JspTag findAncestorWithClass(JspTag from, Class<?> klass) | 第1引数で指定されたタグから見て、第2引数で指定されたクラスに対応する先祖タグを検索する。複数候補がある場合は、タグから最も近いものが返される。該当するタグがない場合はnullを返す。 | |
protected JspFragment getJspBody() | ボディ部のJSPフラグメントを取得する。 | |
protected JspContext getJspContext() | JspContextを取得する。 |
- setJspContext, setJspBody, setParent, getParentのデフォルト実装も用意されているので、開発者が実装する必要はない。
- TagSupportと違い、id属性やkeyとvalueの関連付けなどは提供されない。
- SimpleTagSupportでは全てのフィールド(jspBody, jspContext, parentTag)はprivateで保持されているため、必ずgetterを通じて取得する。
制約 | 説明 | |
---|---|---|
ボディ部の制約 | スクリプト要素を記述することができない。スクリプト要素を記述する場合はクラシックタグハンドラを使う。 | |
tldファイルの<body-content>タグの指定について | JSPは指定不可。empty, scriptless, tagdependentのいずれかを指定する。 |
SimpleTagのボディ部を評価する方法、および、tldファイルの<body-content>タグの値によって評価にどのような違いがあらわれるかを答えよ。
- タグハンドラ内でgetJspBody().invoke(Writer out)メソッドを呼び出して評価する。引数には評価結果を出力するWriterを指定する。引数にnullを与えると、JspContext.getOut()を使用して評価結果を出力する。
- tldファイルの<body-content>タグに応じた評価結果の違い
- scriptlessの場合:
ボディ部のEL式とアクションタグ(標準アクションタグおよびカスタムタグ)が評価され、それ以外はテンプレートテキストとしてそのまま出力される。スクリプト要素を記述するとエラーになる。 - tagdependentの場合:
ボディ部のテキストがそのまま出力される。EL式、アクションタグ、スクリプト要素を記述してもそのままテンプレートテキストとして出力される。
- scriptlessの場合:
- tldファイルの<body-content>タグがscriptlessの場合、子孫タグのボディ部にもスクリプト要素を記述することはできない。
- doTag()メソッド内でSkipPageExceptionをスローすると、タグ以降のJSPページを評価しない。
タグハンドラ共通の設定・機能
動的属性を使用する際に必要な設定・実装作業 | |
---|---|
tldファイルの<tag>タグの下に<dynamic-attributes>タグを記述し、値をtrueにする。 | |
タグハンドラクラスにjavax.servlet.jsp.tagext.DynamicAttributesインターフェースを実装し、属性の処理を記述する。 |
シグネチャ | 説明 | |
---|---|---|
public void setDynamicAttribute(String uri, String localName, Object value) | 動的属性(attributeタグで指定されていない属性)が読み込まれるたびに実行されるメソッド。uri: 属性の名前空間。デフォルトの名前空間の場合はnull。localName: 属性名。value: 属性の値。 |
スクリプティング変数を使用する際に必要な設定・実装作業 | |
---|---|
tldファイルの<tag>タグの下に<variable>タグを記述し、その子タグとして<name-given>または<name-from-attribute>タグを記述して変数名を指定する。 | |
タグハンドラ内のメソッド(doStartTag()など)で、PageContextにスクリプティング変数名をキーとして変数の値を格納する。例: pageContext.setAttribute(varName, "value"); |
- <name-from-attribute>タグを使って変数名を指定する場合、<name-from-attribute>タグで指定した属性を省略するとスクリプティング変数が決定できずにエラーとなる。(Tomcat6.0で確認)
JSPフラグメントの属性に関して以下を答えよ。
- | 説明 |
---|---|
定義方法 |
|
属性に値を指定する方法 | カスタムタグのボディ部に<jsp:attribute>タグを使って属性を記述する。このタグを使用する場合にボディ部を記述する場合は、必ず<jsp:body>タグを使用する。 |
記述できない要素 | スクリプト要素は記述不可。(EL式、アクションタグは記述可能) |
評価方法 | タグハンドラ内でJspFragment#invoke(Writer out)メソッドを呼び出して評価する。引数には評価結果を出力するWriterを指定する。引数にnullを与えると、JspContext.getOut()を使用して評価結果を出力する。 |
検索対象 | 方法 |
---|---|
親タグ |
以下のどちらかを使用。親がいない場合はnullが返される。
|
先祖タグ |
以下のどちらかを使用。複数候補がある場合は、タグから最も近いものが返される。該当するタグがない場合はnullを返す。
|
タグファイル
- | 説明 |
---|---|
保存場所 | WEB-INF/tags、またはWEB-INF/lib/*.jar内のMETA-INF/tags。(どちらもサブディレクトリを許容する) |
ファイル名 | xxx.tag、xxx.tagx(XML形式の場合)。xxxはタグ名として使用される。 |
JSPでの使用方法 | JSPのtaglibディレクティブを記述する。tagdir属性でタグファイル配置場所のディレクトリを、prefix属性でプレフィックスの指定を行う。(例: <%@ taglib tagdir="/WEB-INF/tags/" prefix="tags"%>)
(タグファイルはtldファイルを作成しなくても使えるが、タグファイルに対してtldファイルを作成してuri属性を設定することもできる。その場合は、通常のカスタムタグと同様に、tagdir属性の代わりにuri属性でタグファイルを指定することができる。) |
タグのボディ部に関する制約 | スクリプト要素は記述不可能。(EL式、アクションタグは記述可能) |
暗黙オブジェクト | 型 | |
---|---|---|
jspContext | javax.servlet.jsp.JspContext | |
request | javax.servlet.ServletRequest | |
session | javax.servlet.http.HttpSession | |
application | javax.servlet.ServletContext | |
response | javax.servlet.ServletResponse | |
out | javax.servlet.jsp.JspWriter | |
config | javax.servlet.ServletConfig |
- pageContextではなくjspContextであることに注意。
- page, exceptionはない
種類 | JSP形式タグ | XML形式タグ | 説明 | |
---|---|---|---|---|
tagディレクティブ | <%@ tag 属性="値" ... %> | <jsp:directive.tag 属性="値" ... /> | タグの設定全般を記述する。 | |
attributeディレクティブ | <%@ attribute 属性="値" ... %> | <jsp:directive.attribute 属性="値" ... /> | タグの属性に関する設定。 | |
variableディレクティブ | <%@ variable 属性="値" ... %> | <jsp:directive.variable 属性="値" ... /> | スクリプティング変数の設定。 |
- taglib, includeディレクティブもタグファイル内で使用可能。
- pageディレクティブのみタグファイル内では使用不可。
属性 | デフォルト値 | 説明 | |
---|---|---|---|
body-content | scriptless | ボディ部のタイプを指定。empty, scriptless, tagdependentから指定する。 | |
dynamic-attributes | - | 動的属性を使用する場合に、動的属性の属性名と値を格納するMapの変数名を指定する。 | |
import | java.lang.*, javax.servlet.*, javax.servlet.http.*, javax.servlet.jsp.* | インポートするクラスの指定。カンマ区切りで複数記述可能。 | |
isELIgnored | false | EL式を無視するかどうか。 | |
language | java | 使用する言語。 | |
pageEncoding | ISO-8859-1 | このタグファイルの記述に使用されている文字エンコーディング。 | |
deferredSyntaxAllowedAsLiteral | false | 遅延評価のEL式の記法 #{} をリテラル中でただの文字列とみなすかどうか。 | |
trimDirectiveWhitespaces | false | 通常ディレクティブ行は空行として出力されるが、この属性がtrueの場合、空行を出力しなくなる。 |
- 属性は全て必須ではない。
- 以下の属性もあるが省略した。
- description
- display-name
- example
- large-icon
- small-icon
属性 | 必須 | デフォルト値 | 説明 | |
---|---|---|---|---|
name | ○ | - | 属性名 | |
required | - | false | 必須の属性かどうか。 | |
fragment | - | false | 属性がJSPフラグメントかどうか。 | |
rtexprvalue | - | true | 属性に式の記述を許すかどうか。 | |
type | - | java.lang.String | 属性の型の完全修飾名。 | |
deferredValue | - | true | EL式の遅延評価( #{} )を受け入れるかどうか。 | |
deferredValueType | - | java.lang.String | EL式の遅延評価結果が属する型の完全修飾名。 | |
deferredMethod | - | true | EL式の遅延評価によるメソッド呼び出しを受け入れるかどうか。 | |
deferredMethodSignature | - | - | EL式の遅延評価によるメソッド呼び出しで使用されるメソッドのシグネチャ。 |
- rtexprvalueは、tldファイルではデフォルトfalseだが、attributeディレクティブではデフォルトtrueなので注意。
- 他にdescription属性もあるが省略した。
属性 | 必須 | デフォルト値 | 説明 | |
---|---|---|---|---|
name-given | △ | - | スクリプティング変数の名前を指定する。 | |
name-from-attribute | △ | - | スクリプティング変数の名前が格納された属性を指定する。name-givenとどちらかを指定する必要がある。このタグで指定する属性は rtexprvalue が false でなければならない(デフォルトでtrueなので、明示的にrtexprvalue="false"の指定が必要) | |
alias | △ | - | タグファイル内でスクリプティング変数を扱う場合の変数の別名を定義する。name-from-attributeタグを使用する場合は必ず指定が必要。また、name-given属性と同時には使用できない。 | |
variable-class | - | java.lang.String | スクリプティング変数の型の完全修飾名。 | |
declare | - | true | スクリプティング変数を新たに定義するかどうかをtrueまたはfalseで指定。すでに定義されている変数を使う場合はfalseを指定する。 | |
scope | - | NESTED | スクリプティング変数の有効範囲を以下の3つから指定。AT_BEGIN: 開始タグ以降で有効。 AT_END: 終了タグ以降で有効。 NESTED: カスタムタグのボディ部内のみで有効。 |
- 他にdescription属性もあるが省略した。
タグ | 説明 | |
---|---|---|
<jsp:doBody> | ボディ部の評価を行う。 | |
<jsp:invoke> | JSPフラグメント属性の評価を行う。 |
属性 | 必須 | デフォルト値 | 説明 | |
---|---|---|---|---|
var | - | - | ボディの評価結果を格納する変数を指定する。 | |
varReader | - | - | ボディの評価結果を読み込むReaderを格納する変数を指定。 | |
scope | - | page | varまたはvarReaderで指定した変数のスコープ。page, request, session, applicationから指定する。 |
- varとvarReaderの両方が指定されない場合、タグの位置に評価結果が展開される。
属性 | 必須 | デフォルト値 | 説明 | |
---|---|---|---|---|
fragment | ○ | - | JSPフラグメントを格納する属性名。 | |
var | - | - | JSPフラグメントの評価結果を格納する変数を指定する。 | |
varReader | - | - | JSPフラグメントの評価結果を読み込むReaderを格納する変数を指定。 | |
scope | - | page | varまたはvarReaderで指定した変数のスコープ。page, request, session, applicationから指定する。 |
- varとvarReaderの両方が指定されない場合、タグの位置に評価結果が展開される。