サンプルから学ぶ JSFカスタムタグの実装

2009/07/17 12:50Update
TAGS: JSF | カスタムタグ | タグ | コンポーネント | レンダラー | TLD

JSFでは、<h:inputText /><h:outputText />など多くの標準タグがデフォルトで提供されるほか、カスタムタグの作成もできます。

Page:  <1|2|3|4|5>
本文はJSFカスタムタグの実装手順について解説します。

JSFカスタムタグを実装するには、決まった手順の通りで行えばよい。
その手順は基本的に以下のようになります。
1)タグクラスの実装
  ※タグクラス:JSPタグと直接関わるクラス。
  例えば、<h:outputText />タグのタグクラス:OutputTextTag
2)コンポーネントクラスの実装
  ※コンポーネントクラス:データクラス。
  例えば、<h:outputText />タグのコンポーネントクラス:HtmlOutputText
3)レンダラークラスの実装
  ※レンダラークラス:カスタムタグが送信値のデータ解析、及びタグの表示形態(どんな形で表示するか)を決定するクラス。
  例えば、<h:outputText />タグのレンダラークラス:TextRenderer
4)TLDファイルに登録
  ※拡張子は.tldのファイルで、タグとタグクラスの関連性を定義する役割を果たします。
5)faces-config.xmlに登録
  ※コンポーネント、レンダラーを登録し、JSFに知らせます。

例えば、<m:myTag />を実装するとします。
<m:myTag /> ==*.tld ⇒ MyTag ==faces-config.xml⇒ MyComponent 
                          ⇒ MyRenderer ⇒ HTMLコード ⇒ ブラウザー
(タグ→Javaクラス→HTMLコード)


JSP側のコード
...
<m:myTag value="カスタムタグよ" />
...

タグクラス


JSFタグクラスの階層
javax.servlet.jsp.tagext.Tag
∟javax.faces.webapp.UIComponentTag
  ∟javax.faces.webapp.UIComponentBodyTag

※UIComponentTagはJSFのトップレベルのタグクラスです。他のタグクラスは直接または間接的にこのクラスを継承しています。
※UIComponentBodyTagはボディコンテンツがあるタグに使用されるように設計されています。
 例えば、<h:commandLink>タグ、<h:outputLink>タグ、<f:view>タグ、<f:verbatim>タグなど。
 <f:verbatim>のようなカスタムタグを実装したい場合、UIComponentBodyTagを継承すればよい。

■javax.faces.webapp.UIComponentTag
|-BaseComponentTag
   |-ParameterTag
   |-SelectItemsTag
   ∟SelectItemTag
|-ColumnTag
|-CommandButtonTag
|-DataTableTag
|-FormTag
|-GraphicImageTag
|-InputHiddenTag
|-InputSecretTag
|-InputTextAreaTag
|-InputTextTag
|-MessagesTag
|-MessageTag
|-OutputFormatTag
|-OutputLabelTag
|-OutputTextTag
|-PanelGridTag
|-PanelGroupTag
|-SelectBooleanCheckboxTag
|-SelectManyCheckboxTag
|-SelectManyListboxTag
|-SelectManyMenuTag
|-SelectOneListboxTag
|-SelectOneMenuTag
|-SelectOneRadioTag
|-...
∟SubviewTag

■javax.faces.webapp.UIComponentBodyTag
|-CommandLinkTag
|-OutputLinkTag
|-VerbatimTag
|-...
∟ViewTag


タグクラスを実装するには、UIComponentTag/UIComponentBodyTagクラスもしくはそのサブクラスから継承すれば問題はないでしょう。

例:
package com.syboos.test.taglib;

import javax.faces.webapp.UIComponentTag;
import javax.faces.component.UIComponent;
import javax.faces.el.ValueBinding;

public class MyTag extends UIComponentTag {
    private String value;//タグプロパティと対応

    public String getValue() {    //getterメソッド
        return value;
    }

    public void setValue(String value) {    //setterメソッド
        this.value = value;
    }

    /** 
     * レンダラー・タイプを返します。
     * faces-config.xmlに定義したレンダラークラスと関連する名前
     * 後ほどfaces-config.xml節に説明します。
     * @see javax.faces.webapp.UIComponentTag#getRendererType()
     */
    public String getRendererType() {
        return "com.syboos.faces.test.MyRenderer";
    }

    /**
     * コンポーネント・タイプを返します。
     * faces-config.xmlに定義したコンポーネントクラスと関連する名前
     * 後ほどfaces-config.xml節に説明します。
     * @see javax.faces.webapp.UIComponentTag#getComponentType()
     */
    public String getComponentType() {
        return "com.syboos.faces.test.MyComponent";
    }

    /**
     * タグクラスのデータを変換したり、コンポーネントクラスに設定したりするメソッドです。
     * @see javax.faces.webapp.UIComponentTag#setProperties(UIComponent)
     */
    protected void setProperties(UIComponent component) {
        super.setProperties(component);
        MyComponent my = (MyComponent)component;

        if (value != null) {
            if (isValueReference(value)) {
                ValueBinding vb = getValueBinding(value);
                data.setValueBinding("value", vb);

                my.getAttributes().put("value", value);
            } else {
                data.setValue(value);
            }
        }
        
    }
}


タグクラスの実装方法について、詳しく解説しませんが、大体はこのような感じです。
※実際の実装を行う際に、何か既存のタグクラス(例えばOutputTextTag)を参照すればよいと思います。
※MyComponentはコンポーネントクラスに該当しますので、後ほど説明します。

Page:  <1|2|3|4|5>

有关作者
Syboos.jp編集長システム設計や開発、保守運営などを行ってます。オープンソース技術に興味があります。

Sponsored Link


Comments