JSFによるWebアプリケーション開発 第11回 カスタム・コンポーネント JSFによるWebアプリケーション開発 第11回
ここでの内容 カスタム・コンポーネントの作成方法について学ぶ。
カスタム・コンポーネントの 作成技法
カスタム・コンポーネントとは? JSF では、UIコンポーネントを自分で作ることができる。 こうした、自作したコンポーネントのことを「カスタム・コンポーネント」と言う。
カスタム・コンポーネントの例 (1) <%@ taglib uri="/WEB-INF/blink.tld" prefix="my" %> ......... <f:view> <my:blink>Hello !</my:blink> </f:view>
カスタム・コンポーネントの例 (2) 内容で指定した文字列が点滅する。 HTML の blink タグが使われる
カスタム・コンポーネントの 作成に必要なファイル Javaのプログラム UIコンポーネントクラス タグハンドラクラス レンダラ 設定ファイル タグライブラリディスクリプタ (TLD) faces-config.xml
注意点 Javaプログラムは、必ずパッケージ宣言をすること。パッケージを付けないとうまく動かない。
UIコンポーネントクラス (1) UIコンポーネントの表すクラス すべてのUIコンポーネントは、UIComponentBase クラスを継承する。
UIコンポーネントクラス (2) package blink; import javax.faces.component.UIComponentBase; public class UIBlink extends UIComponentBase { public String getFamily() { return "MyFamily"; }
UIコンポーネントクラス (3) public String getFamily() { return "MyFamily"; } 「コンポーネント・ファミリ」を設定 UIコンポーネントとレンダラを関連づけるために使われる。
タグハンドラクラス (1) JSPからUIコンポーネントを利用するためのクラス 次のいずれかのクラスを継承する UIComponentTag (タグのボディ(=内容)を操作しない場合) UIComponentBodyTag (タグのボディを操作する場合) UIComponentTag で十分な場合が多い
タグハンドラクラス (2) package blink; import javax.faces.webapp.UIComponentTag; public class BlinkTag extends UIComponentTag { public String getComponentType() { return "Blink"; } public String getRendererType() { return "BlinkRenderer";
タグハンドラクラス (3) public String getComponentType() { return "Blink"; } コンポーネントの名前を返す。 faces-config.xml で指定する。
タグハンドラクラス (4) public String getRendererType() { return "BlinkRenderer"; } レンダラの名前を返す。 faces-config.xml で指定する。
レンダラの2つの機能 エンコード デコード HTMLのフォームから入力されたデータを、UIコンポーネントに設定する。 UIコンポーネントから、HTMLを出力する。
レンダラクラス (1) Renderer クラスを継承する。 エンコードには、encodeBegin メソッドと encodeEnd メソッドを使う。
レンダラクラス (2) public class BlinkRenderer extends Renderer { public void encodeBegin(……) { ……… } public void encodeEnd(……) {
レンダラクラス (3) // HTML の開始タグを出力する public void encodeBegin(FacesContext context, UIComponent component) throws IOException { ......... ResponseWriter writer = context.getResponseWriter(); writer.write("<blink>"); }
レンダラクラス (4) // HTML の終了タグを出力する public void encodeEnd(FacesContext context, UIComponent component) throws IOException { ......... ResponseWriter writer = context.getResponseWriter(); writer.write("</blink>"); }
TLDの設定 (1) タグライブラリディスクリプタ = TLD JSPでどんなタグを利用できるか定義するための設定ファイル
TLDの設定 (2) <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>Blink !</short-name> <tag> <name>blink</name> <tag-class>blink.BlinkTag</tag-class> <body-content>scriptless</body-content> </tag> </taglib>
TLDの設定 (3) <tag> <name>blink</name> <tag-class>blink.BlinkTag</tag-class> <body-content>scriptless</body-content> </tag> name 要素はタグの名前 tag-class 要素はタグハンドラクラスの名前 body-content 要素の “scriptless” は、要素の内容にテキストや Value Binding 式などが入ることを示す。
faces-config.xml の設定 (1) UIコンポーネントとレンダラを設定する。
faces-config.xml の設定 (2) <component> <component-type>Blink</component-type> <component-class>blink.UIBlink</component-class> </component> component-type 要素は、タグハンドラクラスのcomponentTypeプロパティ component-class 要素は、UIコンポーネントクラスのクラス名
faces-config.xml の設定 (3) <render-kit> <renderer> <component-family>MyFamily</component-family> <renderer-type>BlinkRenderer</renderer-type> <renderer-class> blink.BlinkRenderer</renderer-class> </renderer> </render-kit>
faces-config.xml の設定 (4) <component-family>MyFamily</component-family> <renderer-type>BlinkRenderer</renderer-type> <renderer-class>blink.BlinkRenderer</renderer-class> component-family 要素は、UIコンポーネントクラスのfamily プロパティ renderer-type 要素は、タグハンドラクラスの rendererType プロパティ renderer-class 要素は、レンダラクラス名
JSPの記述 <%@ taglib uri="/WEB-INF/blink.tld" prefix="my" %> ……… <f:view> <my:blink>Hello !</my:blink> </f:view>
ディレクティブの記述 <%@ taglib uri="/WEB-INF/blink.tld" prefix="my" %> TLD を WEB-INF フォルダに置いておく。
空要素タグ
サンプルプログラム (1) <%@ taglib uri="/WEB-INF/now.tld" prefix="my" %> <my:now />
サンプルプログラム (2) 現在の日時を表示する
UIコンポーネントクラス package now; import javax.faces.component.UIComponentBase; public class UINow extends UIComponentBase { public String getFamily() { return "MyFamily"; }
タグハンドラクラス package now; import javax.faces.webapp.UIComponentTag; public class NowTag extends UIComponentTag { public String getComponentType() { return “Now"; } public String getRendererType() { return “NowRenderer";
レンダラクラス (1) public class NowRenderer extends Renderer { public void encodeBegin(……) { ……… } タグがないので、encodeBegin メソッドだけでよい
レンダラクラス (2) // 現在の日時を表示 public void encodeBegin(FacesContext context, UIComponent component) throws IOException { ......... Date d = new Date(); DateFormat df = DateFormat.getDateTimeInstance(); ResponseWriter writer = context.getResponseWriter(); writer.write(df.format(d)); }
TLDの設定 <tag> <name>now</name> <tag-class>now.NowTag</tag-class> <body-content>empty</body-content> </tag> body-content 要素の “empty” は、このUIコンポーネントが空要素タグで表現されることを示す。
faces-config.xml の設定 (1) <component> <component-type>Now</component-type> <component-class>now.UINow</component-class> </component> component-type 要素は、タグハンドラクラスのcomponentTypeプロパティ component-class 要素は、UIコンポーネントクラスのクラス名
faces-config.xml の設定 (2) <render-kit> <renderer> <component-family>MyFamily</component-family> <renderer-type>NowRenderer</renderer-type> <renderer-class> now.NowRenderer</renderer-class> </renderer> </render-kit>
JSPの記述 <%@ taglib uri="/WEB-INF/now.tld" prefix="my" %> <my:now />
属性の記述
サンプルプログラム (1) <%@ taglib uri="/WEB-INF/now.tld" prefix="my" %> ...... <my:now format="FULL" /><br /> <my:now format="LONG" /><br /> <my:now format="MEDIUM" /><br /> <my:now format="SHORT" /><br />
サンプルプログラム (2) 属性で指定したスタイルに従って、現在の日時を表示する。
UIコンポーネントクラス package now; import javax.faces.component.UIComponentBase; public class UINow extends UIComponentBase { public String getFamily() { return "MyFamily"; }
タグハンドラクラス (1) package now; import javax.faces.webapp.UIComponentTag; public class NowTag extends UIComponentTag { public String getComponentType() { return “Now"; } public String getRendererType() { return “NowRenderer";
タグハンドラクラス (2) protected void setProperties( UIComponent component) { super.setProperties(component); UINow now = (UINow)component; now.getAttributes().put("format", format); } コンポーネントに属性を設定する。
タグハンドラクラス (3) public String getFormat() { return format; } public void setFormat(String format) { this.format = format; 属性値をプロパティとして扱う
レンダラクラス (1) 属性値を取り出し、その値によって必要な処理を行う。
レンダラクラス (2) UINow now = (UINow)component; String format = (String)now.getAttributes().get("format"); if (format.equals("FULL")) { df = DateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL); } else if (format.equals("LONG")) { DateFormat.LONG, DateFormat.LONG);
TLDの設定 (1) <tag> <name>now</name> <tag-class>now.NowTag</tag-class> <body-content>empty</body-content> <attribute> <name>format</name> <required>true</required> </attribute> </tag>
TLDの設定 (2) <attribute> <name>format</name> <required>true</required> </attribute> name 要素で属性名を指定する required 要素でこの属性が必須かどうかを示す。
faces-config.xml の設定 (1) <component> <component-type>Now</component-type> <component-class>now.UINow</component-class> </component> component-type 要素は、タグハンドラクラスのcomponentTypeプロパティ component-class 要素は、UIコンポーネントクラスのクラス名
faces-config.xml の設定 (2) <render-kit> <renderer> <component-family>MyFamily</component-family> <renderer-type>NowRenderer</renderer-type> <renderer-class> now.NowRenderer</renderer-class> </renderer> </render-kit>
JSPの記述 <%@ taglib uri="/WEB-INF/now.tld" prefix="my" %> ...... <my:now format="FULL" /><br /> <my:now format="LONG" /><br /> <my:now format="MEDIUM" /><br /> <my:now format="SHORT" /><br />