上面的例子,表现层的编码,解码工作都是Component自己完成的,但是这样的话,自定义Component的重用行就很差了。
所以这里要自定义一个Renderer来做编码,解码工作。要自定义一个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");
}
}
这个Renderer和之前Component的编码解码过程类似,只是方法上多了一个UIComponent参数,用来表示对应的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>
定义好了之后,只需要把上面自定义的那个Tag文件稍微修改一下就可以了:
…
public String getComponentType() {
//return "test.TextWithCmd";
return "javax.faces.Input";
}
public String
getRendererType() {
//return null;
return "test.TextCmd";
}
…
同样的,你也可以在自定义的Component中设置使用的Renderer。修改上面自定义Component的构造函数就可以了。
大家自己去试一下吧。具体程序参看示例程序。