Component可以自己负责将物件资料编码为HTML文件或其它的输出文件,也可以将这个任务委托给 Renderer,这边先介绍的是让Component自己负责编码的动作。
这边着重的是介绍完成自订元件所必须的流程,所以我们不设计太复杂的元件,这边将完成以下的元件,这个元件会有一个输入文字栏位以及一个送出按钮:

您要继承UIComponent或其子类别来自订Component,由于文字栏位是一个输入栏位,为了方便,您可以继承UIInput类别,这可以让您省去一些处理细节的功夫,在继承UIComponent或其子类别后,与编码相关的主要有三个方法:
- encodeBegin()
- encodeChildren()
- encodeEnd()
其中encodeChildren()是在包括子元件时必须定义,Component如果它的 getRendersChildren()方法传回true时会呼叫encodeChildren()方法,预设上, getRendersChildren()方法传回false。
由于我们的自订元件相当简单,所以将编码的动作写在encodeBegin()或是encodeEnd()都可以,我们这边是定义encodeBegin ()方法:
UITextWithCmd.java
package onlyfun.caterpillar;
import java.io.IOException;
import java.util.Map;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
public class UITextWithCmd extends UIInput {
private static final String TEXT = ".text";
private static final String CMD = ".cmd";
public UITextWithCmd() {
setRendererType(null);
}
public void encodeBegin(FacesContext context)
throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = getClientId(context);
encodeTextField(writer, clientId);
encodeCommand(writer, clientId);
}
public void decode(FacesContext context) {
// .....
}
private void encodeTextField(ResponseWriter writer,
String clientId) throws IOException {
writer.startElement("input", this);
writer.writeAttribute("name", clientId + TEXT, null);
Object value = getValue();
if(value != null) {
writer.writeAttribute("value",
value.toString(), null);
}
String size = (String) getAttributes().get("size");
if(size != null) {
writer.writeAttribute("size", size, null);
}
writer.endElement("input");