上面的例子,表現(xiàn)層的編碼,解碼工作都是Component自己完成的,但是這樣的話,自定義Component的重用行就很差了。
所以這里要自定義一個(gè)Renderer來做編碼,解碼工作。要自定義一個(gè)Renderer,需要繼承javax.faces.render.Renderer:
package
test;
import
java.io.IOException;
import
java.util.Map;
import
javax.faces.component.EditableValueHolder;
import
javax.faces.component.UIComponent;
import
javax.faces.component.UIInput;
import
javax.faces.context.FacesContext;
import
javax.faces.context.ResponseWriter;
import
javax.faces.render.Renderer;
public
class TextCmdRenderer extends Renderer {
private static final String TEXT =
".text";
private static final String CMD =
".cmd";
//編碼
public void encodeBegin(FacesContext
context,
UIComponent component) throws
IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = component.getClientId(context);
encodeTextField(component, writer, clientId);
encodeCommand(component, writer, clientId);
}
//解碼
public void decode(FacesContext context,
UIComponent component) {
Map reqParaMap = context.getExternalContext().
getRequestParameterMap();
String clientId = component.getClientId(context);
String submittedValue =
(String) reqParaMap.get(clientId + TEXT);
((EditableValueHolder) component).setSubmittedValue(
submittedValue);
((EditableValueHolder) component).setValid(true);
}
private void encodeTextField(UIComponent
component,
ResponseWriter writer, String clientId)
throws IOException {
writer.startElement("input", component);
writer.writeAttribute("name", clientId + TEXT, null);
Object value = ((UIInput) component).getValue();
if(value != null) {
writer.writeAttribute("value",
value.toString(), null);
}
String size =
(String) component.getAttributes().get("size");
if(size != null) {
writer.writeAttribute("size", size, null);
}
writer.endElement("input");
}
private void encodeCommand(UIComponent
component,
ResponseWriter writer,
String clientId) throws IOException {
writer.startElement("input", component);
writer.writeAttribute("type", "submit", null);
writer.writeAttribute("name", clientId + CMD, null);
writer.writeAttribute("value", "submit", null);
writer.endElement("input");
}
}
這個(gè)Renderer和之前Component的編碼解碼過程類似,只是方法上多了一個(gè)UIComponent參數(shù),用來表示對(duì)應(yīng)的Component。
faces-config.xml中配置定義的Renderer:
<!-- 自定義Renderer -->
<render-kit>
<renderer>
<component-family>
javax.faces.Input
</component-family>
<renderer-type>
test.TextCmd
</renderer-type>
<renderer-class>
test.TextCmdRenderer
</renderer-class>
</renderer>
</render-kit>
定義好了之后,只需要把上面自定義的那個(gè)Tag文件稍微修改一下就可以了:
…
public String getComponentType() {
//return "test.TextWithCmd";
return "javax.faces.Input";
}
public String
getRendererType() {
//return null;
return "test.TextCmd";
}
…
同樣的,你也可以在自定義的Component中設(shè)置使用的Renderer。修改上面自定義Component的構(gòu)造函數(shù)就可以了。
大家自己去試一下吧。具體程序參看示例程序。