JSFにはじめからあるInputタグbuttonタグなどはUIコンポーネントクラスから作られている。これらを改良してJSFのデフォルトに含まれないタグのコンポーネント化などができるようになる。
例えば、DBからのresultSetを整形してTableで表示するコンポーネントはあるんだけど、カラムの結合などまではできない。こういった処理を組み込んでオリジナルのコンポーネントを作ることで、JSPファイルへの記述を簡単にすることができそう。
じゃつくってみよう
今回はfieldsetタグをJSFのUIにしてしまう。
やること
- UIコンポーネントクラス作成
- タグクラス作成
- レンダラー作成
- TLDファイル作成
- faces-config.xml作成
- JSPに実装
UIコンポーネントクラス作成
UIコンポーネントはUIComponentBaseを継承して作成する。UIコンポーネント内にはタグに書かれた属性名と属性値などが保持される。ページに表示されるテキストボックスなどのコンポーネントをオブジェクトにしたもの・・・みたいな感じ。
package com.daipresents.kingdom.component;
import javax.faces.component.UIComponentBase;
public class UIFieldset extends UIComponentBase {
/** UIコンポーネントFamilyName */
public static final String FAMILY_NAME = "com.daipresents.kingdom.component.UIFieldset";
/** コンポーネントタイプ */
public static final String COMPONENT_TYPE = "com.daipresents.kingdom.component.UIFieldset";
/**
* FamilyNameを取得します。
*/
public String getFamily() {
return FAMILY_NAME;
}
}
- FamilyName、ComponentTypeにはこのクラスのパッケージ名を利用することにした。デフォルトのUIFormでは「javax.faces.Form」になっていた。
- ComponentTypeはUIが持ってもいいかなと思って実装した。これもパッケージ名を利用。
- FamilyNameのGetterだけを実装。
タグクラス作成
UIコンポーネントとは別に、JSP用のタグクラスが必要になる。これはJSPに書かれたタグリブの内容をUIコンポーネントに設定する役割をしている。
package com.daipresents.kingdom.taglib;
import javax.faces.component.UIComponent;
import javax.faces.webapp.UIComponentTag;
import com.daipresents.kingdom.component.UIFieldset;
import com.daipresents.kingdom.renderkit.FieldsetRenderer;
public class FieldsetTag extends UIComponentTag {
/** CSS指定用のstyle属性 */
private String style;
/**
* CSSを取得します。
* @return CSSクラス名
*/
public String getStyle() {
return style;
}
/**
* CSSを設定します。
* @param style
*/
public void setStyle(String style) {
this.style = style;
}
/**
* コンポーネントタイプを取得します。
*/
public String getComponentType() {
return UIFieldset.COMPONENT_TYPE;
}
/**
* RendererTypeを取得します。
*/
public String getRendererType() {
return FieldsetRenderer.RENDERER_TYPE;
}
/**
* タグに設定された属性を設定します。
*/
protected void setProperties(UIComponent component) {
super.setProperties(component);
UIFieldset fieldset = (UIFieldset)component;
fieldset.getAttributes().put("style", this.style);
}
}
- ComponentTypeとRendererTypeはこのタグクラスに関連するUIコンポーネント、Rendererからとってきている。
- 今回はstyle属性を使用できるfieldsetコンポーネントを作成した。
- setProperties()メソッドによってJSPに書かれたタグの属性値を取得している。属性の数だけアクセッサが必要になる。
レンダラー作成
Rendererはタグクラスが出力する内容を記述する。タグを書いた部分がResponseWriterによって置き換えられるわけ。
package com.daipresents.kingdom.renderkit;
import java.io.IOException;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;
import com.daipresents.kingdom.component.UIFieldset;
public class FieldsetRenderer extends Renderer {
/** RendererType */
public static final String RENDERER_TYPE = "com.daipresents.kingdom.renderkit.FieldsetRenderer";
/**
* 開始タグを出力します。
*/
public void encodeBegin(FacesContext context, UIComponent component)
throws IOException {
ResponseWriter writer = context.getResponseWriter();
UIFieldset fieldset = (UIFieldset)component;
String style = (String)fieldset.getAttributes().get("style");
writer.startElement("fieldset", component);
writer.writeAttribute("class", style, null);
}
/**
* 終了タグを出力します。
*/
public void encodeEnd(FacesContext context, UIComponent component)
throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.endElement("fieldset");
}
}
- 開始タグ、終了タグを指定する。
- 空要素OKの場合はencodeBegin()メソッドだけでもよいみたい。
TLDファイル作成
タグを利用できるようにTDLファイルに追記する。
<tag>
<name>fieldset</name>
<tag-class>com.daipresents.kingdom.taglib.FieldsetTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>style</name>
<required>false</required>
</attribute>
</tag>
- body-content要素は「empty」だと空要素OK。「JSP」だとタグの内側にJSPが書けるようになる。
- required要素によって属性が必須かどうかを指定できる。
faces-config.xml作成
UIコンポーネントの登録、UIコンポーネントに関連するRendererなどを指定する。
<component>
<component-type>com.daipresents.kingdom.component.UIFieldset</component-type>
<component-class>com.daipresents.kingdom.component.UIFieldset</component-class>
</component>
<render-kit>
<renderer>
<component-family>com.daipresents.kingdom.component.UIFieldset</component-family>
<renderer-type>com.daipresents.kingdom.renderkit.FieldsetRenderer</renderer-type>
<renderer-class>com.daipresents.kingdom.renderkit.FieldsetRenderer</renderer-class>
</renderer>
</render-kit>
- component-type、component-family、renderer-typeには作成したクラスで指定している値を設定する。
JSPに実装
<f:view>
<h:form>
<kd:fieldset style="loginfieid">
・
・
・
画面は以下のようになる。
ソースは以下。
<fieldset class="loginfieid">