JSF2自定義組件編程系列 第三部分 – JAVA編程語言程序開發技術文章

本節將實現一個HtmlInput tag,仍然是Noncomposite Component。接受用戶的輸入,點擊按鈕後,會顯示用戶輸入的信息。有朋友要看效果圖,我也想show一下,可是圖片上傳失敗。在這個系列文章結束的時候,我會上傳我的代碼。


 


  基本流程是,用戶在初始頁面上輸入數據,點擊按鈕後,一般采用PostBack的方法將數據傳遞到JSF的 Serverlet,在後臺的Renderer的decode方法內部通過 FacesContext.getExternalContext().getRequestParameterMap()獲取Map對象,然後通過 key去查找用戶的輸入數據。key是什麼?這裡采用clientIdValue:InputField的格式。
   需要解釋一下ClientId,JSF定義瞭一個規則,為瞭知道是哪一個Tag,程序員可以通過下面的方法在頁面初始化的時候輸出ClientId到客戶端:(實際上一般都是賦給瞭HTML tag的 name屬性)


writer.writeAttribute(“name”, clientIdValue, “clientId”);//第三個參數必須是”clientId”,是JSF內部使用的。


  然後當客戶端提交數據後,UIComponent可以通過調用成員函數getClientId(context)獲得這個clientIdValue。在我這個例子裡面,我在頁面初始化的時候將從調用component.getClientId()或得clientIdValue並輸出到客戶端,用來標志我的HtmlInput tag,然後在下次客戶提交的時候拿回來。但是由於我的HtmlInput tag內部有三個子tag,一個輸入,一個按鈕,一個輸出,對於前兩個,也需要ClientId標志它們,我使用瞭父ClientIdValue+區分字符+子tag名稱的做法。默認區分字符是:。因此,當獲取到HtmlInput tag的ClientId後,拼接出輸入子tag的ClientId:”ClientIdValue:InputField”,將其作為key從map中檢索用戶填入的數據。所以ClientId對於檢索輸入數據非常重要,要想能檢索到,你必須按照JSF的規則先在初始化的時候給需要的tag設置ClientId,以後才能拿回來作為key從Map中使用。


  區分字符是可以修改的,通過在web.xml文件中配置 context-param下的javax.faces.SEPARATOR_CHAR.這個以後用到CSS的時候再說。
現在秀一下代碼,Renderer的代碼:
package com.freebird.renderer;


import com.freebird.component.HtmlInput;
import javax.faces.render.Renderer;
import javax.faces.context.ResponseWriter;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.component.UINamingContainer;
import java.util.Map;



/**
  * Describe class HtmlInputRenderer here.
  *
  *
  * Created: Wed Dec 29 12:14:24 2010
  *
  * @author <a href=”chenshumailto:chenshu@csdesktop”>chenshu</a>
  * @version 1.0
  /
public class HtmlInputRenderer extends Renderer {


  public void decode(FacesContext context, UIComponent component) {
    Map requestMap = context.getExternalContext().getRequestParameterMap();
    String clientId = component.getClientId(context);
    char sep = UINamingContainer.getSeparatorChar(context);
    String symbol = ((String) requestMap.get(clientId + sep + “inputfield”));
    HtmlInput myComponent = (HtmlInput)component;
    myComponent.setSubmittedValue(symbol);
  }


  @Override
  public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
    String clientId = component.getClientId(context);
    char sep = UINamingContainer.getSeparatorChar(context);
    encodeInputField(context, clientId + sep + “inputfield”,component);
    encodeSubmitButton(context, clientId + sep + “submit”,component);
    encodeOutputField(context,component);
  }


  private void encodeInputField(FacesContext context, String clientId, UIComponent component) throws IOException {
    // Render a standard HTML input field
    ResponseWriter writer = context.getResponseWriter();
    writer.startElement(“input”, component);
    writer.writeAttribute(“type”, “text”, null);
    writer.writeAttribute(“name”, clientId, “clientId”);
    HtmlInput myComponent = (HtmlInput)component;
    String value = (String)myComponent.getSubmittedValue();
    if (value != null) {
      writer.writeAttribute(“value”, value, “value”);
    }
    writer.writeAttribute(“size”, “6”, null);
    writer.endElement(“input”);
  }



  private void encodeSubmitButton(FacesContext context, String clientId , UIComponent component) throws IOException {
    // render a submit button
    ResponseWriter writer = context.getResponseWriter();
    writer.startElement(“input”, component);
    writer.writeAttribute(“type”, “Submit”, null);
    writer.writeAttribute(“name”, clientId, “clientId”);
    writer.writeAttribute(“value”, “Click Me!”, null);
    writer.endElement(“input”);
  }


  private void encodeOutputField(FacesContext context,UIComponent component) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    String hellomsg = (String) component.getAttributes().get(“value”);
    writer.startElement(“p”, component);
    writer.writeText(“You entered: ” + hellomsg, null);
    writer.endElement(“p”);
  }
}


UIComponent的代碼,HtmlInput類僅僅繼承瞭UIInput類,所以自然擁有瞭getFamily,get/setSubmittedValue方法的實現。
package com.freebird.component;


import javax.faces.component.UIInput;


/*
  * Describe class HtmlInput here.
  *
  *
  * Created: Wed Dec 29 11:43:18 2010
  *
  * @author <a href=”chenshumailto:chenshu@csdesktop”>chenshu</a>
  * @version 1.0
  /
public class HtmlInput extends UIInput {


}


現在看一下兩個配置文件:
faces-config.xml中添加


  <component>
    <component-type>HtmlInput</component-type>
    <component-class>com.freebird.component.HtmlInput</component-class>
  </component>
  <render-kit>
    <renderer>
      <component-family>javax.faces.Input</component-family>
      <renderer-type>HtmlInputRenderer</renderer-type>
      <renderer-class>com.freebird.renderer.HtmlInputRenderer</renderer-class>
    </renderer>
  </render-kit>


helloworld.taglib.xml中添加
  <tag>
    <tag-name>htmlinput</tag-name>
    <component>
      <component-type>HtmlInput</component-type>
      <renderer-type>HtmlInputRenderer</renderer-type>
    </component>
  </tag>



在web應用程序中使用該tag很簡單,僅僅是一行:
<cs:htmlinput/>

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *