イントラマートでSAStrutsのTaglibを自作!TLDファイルの記述や外部JSPの読み込み方法は?
もともとSAStrutsなどのJava開発フレームワークの基盤では
Taglibと言われるタグライブラリ(API)がいくつか用意されています。
JSPファイル上でTaglibをインポートして、prefix指定することで、
提供されているプラグイン・ライブラリが使い放題になります。
一度記述さえしておけば、そのファイル上ならどこでも呼び出せる上に、
ウェブコンテンツを生成する際には便利な機能が豊富で画面デザイン・処理を共通化できるのが特徴的です。
イントラマートにも専用のTaglibがあり、私も頻繁に利用しています。
開発しているプロジェクトの画面・機能を共通化するには非常にありがたいですね。
このTaglibの目的は共通利用する処理をプラグイン化したり、
JSP上で毎回似たような記述・処理をコーディングする手間を大幅にカットできるなど
チーム開発する上ではかなりの効果を発揮します。
とにかく一度作ってしまえばものすごく楽なものです。
タグライブラリとは?
タグライブラリについてあまり知らない方もいらっしゃるかもしれませんので、
軽くどんなものかを書いていこうと思います。
知っている方は飛ばしてかまいません。
まずタグライブラリは簡単に説明すると
ウェブコンテンツ上で実装できるHTMLタグのような記述文のこと指します。
JSPプログラマ用のタグの作成に使用できる強力な機能が提供されています。
例えば、JSPファイルのヘッダ部に以下のタグライブラリのインポート文を書き加えたとします。
1 | <%@ taglib prefix="imui" uri="http://www.intra-mart.co.jp/taglib/imui"%> |
その後述の任意の場所に以下のカスタムタグを利用します。
1 2 3 4 5 6 7 8 | <imui:tabs> <imui:tabItem title="1番目のタブ" > <input type="text" name="first" value="1番目の値" /> </imui:tabItem> <imui:tabItem title="2番目のタブ" > <input type="text" name="first" value="2番目の値" /> </imui:tabItem> </imui:tabs> |
この例のタグライブラリはイントラマート専用のものになりますが、
JSP上にインポートしたタグライブラリの機能を利用できます。
ちなみに最初のインポート文のprefix属性に指定した「imui」という文字列を
そのままカスタムタグに使用しています。
この「imui」を識別して裏側でサーバサイドJavaプログラムの処理が実行され、
処理結果がJSP上に出力される仕組みです。
実際にこのカスタムタグを実装したウェブページを確認するとこのようになっています。
前述のカスタムタグがJavaプログラムにより変換され
タブが2個あるボックスがHTMLタグとして出力されていますね。
ここからはそんなTaglibを簡単に作ることができますので、
その方法を今回ご紹介したいと思います。
Taglibを生成するにはTagインターフェースを実装
JSPタグライブラリを実装するには制御用のJavaクラスを実装する必要があります。
とりあえず定義するJavaクラスは複雑な処理をしないのであれば、ひとつで構いません。
パッケージ名も任意のもので問題ないです。
この例で列挙するクラス名は「SampleTag」にしたいと思います。
必要なメソッドも含め以下に記述しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | package jp.co.jisakupc-technical.app.tags.myprogram; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.BodyContent; import javax.servlet.jsp.tagext.BodyTag; import javax.servlet.jsp.tagext.Tag; /** * 【共通タグライブラリ】サンプルカスタムタグを出力する処理. * * @version $Revision$ * @author yokki * @created 2015/11/14 */ public class SampleTag implements Tag, BodyTag { /** ページコンテキスト. */ private PageContext pageContext; /** ボディ部コンテント. */ private BodyContent bodyContent; /** 親タグ(インターフェース). */ private Tag parentTag; /** JSPのカスタムタグで指定した属性値. */ private String title; private String value; /** ファイルパス(外部JSPの読み込み). */ private final String OTHER_JSP = "/WEB-INF/view/jp/co/jisakupc_technical/tags/sample.jsp"; /** * ページコンテキストを登録. */ public void setPageContext(PageContext pageContext) { this.pageContext = pageContext; } /** * ボディー部ページコンテントを登録. * * SKIP時は実行されない。 * tldファイルの<body-content>の値がemptyでは実行されない。 */ public void setBodyContent(BodyContent bodyContent) { this.bodyContent = bodyContent; } /** * 親タグの登録. */ public void setParent(Tag parentTag) { this.parentTag = parentTag; } /** * 親タグの取得. */ public Tag getParent() { return this.parentTag; } // ===== ユーザ定義メソッド. ===== /** * 属性値titleの登録. * @param title タイトル */ public void setTitle(String title) { this.title = title; } /** * 属性値valueの登録. * @param velue 名前 */ public void setValue(String value) { this.value = value; } /* ===================================== * タグライブラリの実装メソッドの定義. * ===================================== */ /** * 【実装タグの開始部のHTML出力】 * 開始タグ実装時の処理メソッド. * @return ボディ部の評価 */ public int doStartTag() throws JspException { try { // JSP上の実装タグ開始位置にHTMLタグを出力 JspWriter out = pageContext.getOut(); out.write("<div style=\"width:300px;height:200px;background:#55F;\">"); out.write("<b>" + title +"</b>"); } catch (Exception e) { throw new JspException("SampleTag#doStartBody", e); } // ボディ部の処理を実行 return EVAL_BODY_BUFFERED; } /** * ボディ部の初期処理メソッド. */ public void doInitBody() throws JspException { } /** * 【実装タグの中間部のHTML出力】 * ボディ部の終了処理メソッド. * @return ボディ部の評価 */ public int doAfterBody() throws JspException { // サーブレットリクエストのパラメータ登録 ServletRequest request = pageContext.getRequest(); request.setAttribute("value", value); try { // 実装ファイル(JSP)の記述を出力 pageContext.getServletContext() .getRequestDispatcher(OTHER_JSP) .include(pageContext.getRequest(), pageContext.getResponse()); } catch (ServletException | IOException e) { e.printStackTrace(); } try { // ボディコンテントの文字列情報を取得 String str = bodyContent.getString(); str = "<div id=\"bodyDiv\">" + str + "</div>"; // ボディコンテンツを初期化 bodyContent.clear(); // 生成した文字列データを登録 bodyContent.print(str); // ボディコンテントの取得 JspWriter out = bodyContent.getEnclosingWriter(); // ボディコンテントの出力処理 bodyContent.writeOut(out); } catch (Exception e) { throw new JspException("SampleTag#doAfterBody", e); } return SKIP_BODY; } /** * 【実装タグの終了部のHTML出力】 * 終了タグ実装時の処理メソッド. * @return ボディ部の評価 */ public int doEndTag() throws JspException { try { // JSP上の実装タグ終了位置にHTMLタグを出力 JspWriter out = pageContext.getOut(); out.write("</div>"); } catch (Exception e) { throw new JspException("SampleTag#doEndBody", e); } return EVAL_PAGE; } /** * 最終処理メソッド. * タグ処理を開放します。 */ public void release() {} } |
かなり長いですが、ここまでのJavaの記述によって、
タグライブラリの実装処理が行なわれます。
正直なところこれを見ただけでもピンとこないと思いますので、
ソースコード内のコメント「タグライブラリの実装メソッドの定義.」以下のメソッドを見て下さい。
フローチャートで表すとこのような処理になっています。
JSPで実装したカスタムタグを識別して、上記の処理フローが流れていきます。
「カスタムタグの開始」までに、JSP上のタグ情報、
カスタムタグに指定した属性などの情報をセッターメソッドを通してフィールド変数に格納します。
今回の例ではインターフェースにTagとBodyTagを使用していますが、
BodyContent(タグを囲った中間部分の文字列データ)を使わないのであればTagだけの実装で問題ないです。
ちなみに中間部分とは以下の通りです。
1 | <開始タグ> {中間部分} </終了タグ> |
まず初めにdoStartTagメソッドで実装した処理が動作します。
JspWriterクラスでPageContext(タグを実装したJSPのページ情報)を取得して、
printもしくはwrite関数で開始タグが記述された位置に文字列データを出力できます。
戻り値はint型ですが、その値によってフローの動きが変化します。
指定する戻り値はフローを参考にしてもらえば良いと思います。
インターフェースにBodyTagを実装していないと
「EVAL_BODY_BUFFERED」「EVAL_BODY_AGAIN」を使用できませんのでご注意を。
まあ、各メソッドただ順番通りにメソッドが呼び出されているだけなので、
カスタムタグを通してJSPに出力したい情報を位置関係を考えてコードを書いてあげるだけですね。
慣れれば非常にシンプルで単純な処理です。
ここまでが処理の説明でしたが、
カスタムタグではJSPに記述したタグに属性値を指定できます。
詳しい内容は次のtldファイルのところでお話ししますが、
好きな属性名とその値を指定することで、その属性名及び値をJava側で利用できます。
Taglibを作成するにはTLDファイルの生成・記述が必須
作成したTaglibをウェブサーバ側に認識させるにはtldファイルというものが必要になります。
このtdlファイルはTag Library Descriptorの略のことで、
タグライブラリを作成する場合に使います。
JSPで実装したタグリブのカスタムタグとJavaの処理を結合するための中間ファイルのようなものです。
このファイルがある意味一番重要です。
まずは以下のtldファイルの記述を確認して下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <?xml version="1.0" ?> <!-- ** * 【タグライブラリ】定義ファイル. * JSP上で利用可能なタグライブラリを管理します。 * * @author yokki * @created 2015/11/14 * @update 2015/11/14 * --> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>yokki-tag</short-name> <!-- ===== プラグインの定義. ===== --> <tag> <!-- タグの名称(JSPで呼出し時に使用). --> <name>sampleTag</name> <!-- 処理するクラス(クラスパスを指定). --> <tag-class>jp.co.jisakupc-technical.app.tags.myprogram.SampleTag</tag-class> <!-- BodyContentを使用するか(使用しないならemptyを指定). --> <body-content>JSP</body-content> <attribute> <!-- title属性(setTitleメソッドで格納される). --> <name>title</name> <!-- // 変数名 --> <required>true</required> <!-- // 属性指定を必須にするか trueの場合JSPで未設定時500エラー --> <rtexprvalue>true</rtexprvalue> <!-- // 動的な値を許可するか trueで良いと思います --> </attribute> <attribute> <!-- value属性(setValueメソッドで格納される). --> <name>value</name> <required>false</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib> |
手始めに用意したSampleTagクラスの実装に合わせて、tldファイルに必要な情報を記載しています。
最初のタグの記述は共通のものになるので、tldファイルを生成時は合わせて書きます。
重要な部分は「プラグインの定義.」コメント行以下になります。
<tag>タグに囲まれた部分がカスタムタグの設定部分の記述になります。
詳しい説明はソースコード上に載せています。
<tag>タグ内の<attaribute>はカスタムタグの属性値の設定部分です。
使用したい属性を任意で追加できますので、使いたい分だけattributeタグを記述します。
さらに<tag></tag>部分の記述を付け加えることで、別のタグリブの処理も一括で記述できます。
その場合はJavaクラスも並行して用意する必要はありますね。
記述したtldファイルはウェブサーバ上のとあるディレクトリに配置します。
1 | C:\intra-mart\resin-pro-4.0.43\webapps\imart\WEB-INF\tld\yokki-tags.tld |
上記はイントラマートで使用しているresinサーバのフォルダパスを指定しています。
「imart」はアプリケーション名でイントラマートで利用しているルートディレクトリです。
基本的には「WEB-INF」直下の「tld」に配置すれば良いでしょう。
tldファイルの名前は任意で構いません。(今回はyokki-tags.tldにします。)
ここまで用意することでやっとJSP上でカスタムタグを使用できるようになります。
タグライブラリで外部JSPを読み込みリクエストを送信する方法
おまけですが、今回実装したJavaクラスのソース内に、
sample.jspという外部JSPを読み込む処理を記載しています。
doAfterBodyメソッドの冒頭に記述したソース文です。
1 2 3 4 5 6 7 8 9 10 11 12 | // サーブレットリクエストのパラメータ登録 ServletRequest request = pageContext.getRequest(); request.setAttribute("value", value); try { // 実装ファイル(JSP)の記述を出力 pageContext.getServletContext() .getRequestDispatcher(OTHER_JSP) .include(pageContext.getRequest(), pageContext.getResponse()); } catch (ServletException | IOException e) { e.printStackTrace(); } |
分かりづらいので5~12行目の処理を見ます。
pageContextというカスタムタグ呼び出し元のページ情報に、
getServletContext().getRequestDispatcher(OTHER_JSP)という記述で、
外部JSPファイルの情報をリクエストパラメータとして渡しています。
さらにincludeメソッドでpageContext内に存在するリクエスト情報を、
外部JSPにセットします。
ちなみに1~3行に実装したサーバリクエストのパラメータも含まれます。
この1~3行目の処理はpageContext内にvalueというIDでカスタムタグのvalue属性値をそのままセットしています。
1 2 3 4 5 6 7 8 9 10 | // ボディコンテンツを初期化 bodyContent.clear(); // 生成した文字列データを登録 bodyContent.print(str); // ボディコンテントの取得 JspWriter out = bodyContent.getEnclosingWriter(); // ボディコンテントの出力処理 bodyContent.writeOut(out) |
最後の方で外部JSPの情報を含めた文字列データをボディコンテントに出力しています。
ボディコンテントはカスタムタグの開始タグと終了タグの間に出力されます。
仕組みとしては以上です。
あとは今回使用する外部JSPファイルをサーバリソースに定義します。
sample.jsp
1 2 3 4 5 | <%@page pageEncoding="UTF-8"%> <%@page import="jp.co.intra_mart.foundation.security.message.MessageManager" %> <!-- SampleTagクラスのvalueをサーバリクエストを通して受け取る. --> <input type="text" value="${value}" /> |
タグライブラリをJSP上で実装し呼出す
試しに、今回作成したタグライブラリのカスタムタグを出力させたいJSPに記述してみます。
1 2 3 4 5 6 7 8 9 | <%@page pageEncoding="UTF-8"%> <!-- タグライブラリの定義. --> <%@ taglib prefix="yokki" uri="/WEB-INF/tld/yokki-tags.tld" %> <!-- カスタムタグの実装. --> <yokki:sampleTag title ="タイトル" value="値を表示します"> <p>ボディ部の記述</p> </yokki:sampleTag> |
記述してウェブブラウザで確認すると以下のような状態になると思います。
サンプル用に作ったものなので味気ないデザインですが、
画面上に表示されているものを確認しながらご紹介しましたソースを見ると、
処理から表示するまでの流れがわかると思います。
以上で自作タグライブラリをイントラマートで使用することができます。
最新記事 by よっき (全て見る)
- 「圧着」と「圧接」の違い!コネクタを使った効率的な配線作業! - 2019年10月26日
- 夏の暑さ対策は大丈夫?冷却性能抜群のおすすめCPUクーラー!メモリに干渉しない最強の商品を紹介! - 2018年5月1日
- 自作PC弐号機のケースを換装!SilverStone製のミニタワーで冷却性とかっこよさを追求! - 2018年3月11日
スポンサードリンク