minimize

事業拡大のため、新しい仲間を募集しています。
→詳しくはこちら

StrutsやJSFなどのWebアプリケーションフレームワークは
全てこのJSP拡張タグライブラリによって作られています。
既存のものに満足できないあなた、是非一度自作のタグライブラリを作ってみましょう。

Javaファイルの構造

いきなりこんな突っこんだ所から話すのも何ですが、
これを知っておいた方がタグライブラリの製作において有利です。
JSPファイルはまず HttpServlet を継承したJavaファイルに変換されます。
Tomcatの場合、HttpJspBase の継承クラスになります。
エントリメソッドは _jspService です。

エントリメソッドの処理概要

まず出力コンテキストタイプの設定、PageContextインスタンスの生成などを行います。
そしてJSPの出力を行います。

出力中に発生した全ての例外(Throwable)はcatchされ、そのまま上位にthrowされます。
この場合 web.xmlerror-page の設定をしていなければ、デフォルトのエラー画面に遷移します。
JSPのコンパイルエラーが発生した場合は、画面が真っ白になり
コンソールにエラーメッセージが出力されます。

タグライブラリが一つも存在しない場合、出力メソッドは唯一です。
JSPの出力が完了すれば、このメソッドも処理を終了します。

タグライブラリの宣言

タグライブラリを使うには、JSPの先頭でそれを宣言する必要があります。

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

各属性の意味は次の通りです。

prefix

タグライブラリに用いるタグ名を指定します。
この場合、JSP内で<c という部分を見つけると
JSPパーサがそれを拡張タグライブラリだと判断します。
原理上は html などの標準HTMLタグを指定する事も可能かもしれませんが
混乱の元になるので止めておいた方が良いでしょう。

uri

タグライブラリの実装場所(uri)を記述します。
ただしこのuriは別名(alias)のようなもので、実際の実装ファイルは別の場所にあります。
web.xmltaglib 要素中に
uri(別名)とlocation(実際のtldファイル)の関連付けがあります。

タグライブラリの使用

実際にJSP内でタグライブラリを使ってみます。
ここでは ctag というprefixを使用します。

test string.
<ctag:test>
  test string in tag.
</ctag:test>

これによって生成されるJavaファイルは次のようになります。
なお、簡略化のためにメソッド名などは変えてあります。

out.write("test string\r\n");
if (_ctag_test_0(pageContent)) {
  return;
}

ctag で囲まれていない部分は、通常通りwrite文で出力されます。
そして、ctag で囲まれた部分は別メソッドで処理されることになります。
では、肝心の別メソッド内を見てみましょう。
なお、説明のために若干省略してあります。

private boolean _ctag_test_0(PageContext pageContext) {
  TestTag tag = _pool.get(TestTag.class);
  tag.setPageContext(pageContext);
  if (tag.doStartTag() != SKIP_BODY) {
    do {
      out.write("test string in tag.\r\n");
      if (tag.doAfterBody() != EVAL_BODY_AGAIN) {
        break;
      }
    } while (true);
  }
  if (tag.doEndTag() == SKIP_PAGE) {
    return true;
  }

return false;

}

まず、プールから TestTag クラスのインスタンスを取得します。
次に、doStartTag メソッドを呼び出します。
ここでメソッドが SKIP_BODY を返すと、ctagタグ内の評価は一切行われません。

メソッドが他の値(通常はEVAL_BODY_INCLUDE)を返すと、ctagタグ内の評価が始まります。
まずはctagタグ内をそのまま出力します。
もちろんこの中にさらに拡張タグがあれば、そのメソッドを呼び出すことになります。
そして、doAfterBody メソッドを呼び出します。
このメソッドが EVAL_BODY_AGAIN を返すと、再びタグ内を評価します。
ループ等を実装する場合に利用します。
メソッドが他の値(通常はSKIP_BODY)を返すと、タグの評価を終了します。

最後に、doEndTag メソッドを呼び出します。
このメソッドが SKIP_PAGE を返すと、trueを返して終了します。
他の値(通常はEVAL_PAGE)を返すと、falseを返して終了します。
この戻り値は呼び出し側で判断され、trueの場合はその後のJSP出力を一切行わずに
処理を完了します。このような動作はあまり使う機会は無いかもしれません。