自定义JSF组件<o:p></o:p>
个人感觉,写一个jsf的组件比jsp的标签要复杂得多,因为jsp的标签,只有生成html代码的功能,jsf组件还有如增加事件,增加效验,返回用户反馈的值。等等!一个组件一般是分三部分,扩展UIComponent、定义标签、定义渲染器、。现在我就以一个最简单的例子,制作一个输出CLOB的组件来说明一下组件的建立的基本步骤<o:p></o:p>
第一步:扩展UIComponent,他有一个实现类UIComponentBase,一般最基础的组件就是从这个类里扩展而来的,如果你在客户端显示Bean中的字段,你需要实现ValueHolder接口字段,如UIOutput组件;如果有返回值的话,还需要你实现EditableValueHolder接口,如UIInput组件。一般情况下,如果没有返回值就可以继承UIOutput组件,如果有返回值实现UIInput组件。这样,我们只要这样就可用以下代码就可以实现一个组件部分的编写<o:p></o:p>
- package dinner.view.jsf.uicomponent;
- import javax.faces.component.UIOutput;
- public class OutputClobComponent extends UIOutput{
- public static final String COMPONENT_TYPE = "dinner.Clob";
- public static final String COMPONENT_FAMILY = "dinner.Clob";
- private static final String DEFAULT_RENDERER_TYPE = "dinner.Clob";
- public OutputClobComponent () {
- setRendererType(DEFAULT_RENDERER_TYPE);
- }
- @Override
- public String getFamily(){
- return COMPONENT_FAMILY;
- }
- }
<o:p></o:p>
在构函数中的setRendererType(COMPONENT_FAMILY) 和getFamily 是指定用来生成HTML代码的渲染器,渲染器需要在faces-config.xml中进行配制,关于配制,在最后一步我会进行说明的。<o:p></o:p>
<o:p> </o:p>
第二步,定义渲染器。渲染器我们需要从Renderer类中继承,不过我们一般情况下会继承HtmlRenderer这个类,我们可以覆盖decode encodeBegin encodeChildren encodeEnd 来生成HTML,在这里,和自定义jsp标签的几个方法十分的相似,所以就不深入的说下去了,我们看一下例子。 <o:p></o:p>
- package dinner.view.jsf.uicomponent;
- import java.io.IOException;
- import java.sql.Clob;
- import java.sql.SQLException;
- import javax.faces.component.UIComponent;
- import javax.faces.context.FacesContext;
- import javax.faces.context.ResponseWriter;
- import org.apache.myfaces.shared_impl.renderkit.RendererUtils;
- import org.apache.myfaces.shared_impl.renderkit.html.HtmlRenderer;
- public class OutputClobRender extends HtmlRenderer{
- @Override
- public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
- RendererUtils.checkParamValidity(context, component, null);
- Clob clob = (Clob)RendererUtils.getObjectValue(component);
- ResponseWriter writer = context.getResponseWriter();
- String strValue = "";
- try {
- strValue = clob.getSubString(1,(int)clob.length());
- } catch (SQLException e) {
- e.printStackTrace();
- }
- writer.write(strValue);
- }
- }
<o:p></o:p>
因为例子很简单,所以只覆盖了encodeEnd方法。在这里,我们用到了RendererUtils类,在这个类里有很多的静态方法,如RendererUtils.getObjectValue是为了得到以这个控件绑定的字段。<o:p></o:p>
第三步,定义标签,在这一步中我们需要继承UIComponentTag这个类,但在实际应用中,我们可以继承他的子类,比如在例子中我们就继承HtmlOutputTextTagBase。在标签类中,我们必须要覆盖getComponentType方法和getRendererType,来指定这个标签属于哪个组件和渲染器,这两个属性的返回值都应和配制文件指定的值相同。<o:p></o:p>
- package dinner.view.jsf.uicomponent;
- import org.apache.myfaces.shared_impl.taglib.html.HtmlOutputTextTagBase;
- public class OutputClobTag extends HtmlOutputTextTagBase{
- @Override
- public String getComponentType() {
- return OutputClobComponent.COMPONENT_TYPE;
- }
- @Override
- public String getRendererType() {
- return "dinner.Clob";
- }
- }
<o:p></o:p>
在建立后tag类后,我们还需要做建一个tag文件,这样才能使用这个组件,在这里,和jsp自定义标签是一样的,所以也不再详述了,以下是代码<o:p></o:p>
<o:p></o:p>
<o:p></o:p>
xml 代码
- xml version="1.0" encoding="ISO-8859-1" ?>
- PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
- "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
- <taglib>
- <tlib-version>0.03tlib-version>
- <jsp-version>1.2jsp-version>
- <short-name>dinnercnshort-name>
- <uri>http://www.dinnercn.com/jsf/ uri>
- <tag>
- <name>clobname>
- <tag-class>
- dinner.view.jsf.uicomponent.OutputClobTag
- tag-class>
- <attribute>
- <name>valuename>
- attribute>
- tag>
- taglib>
<o:p></o:p>
<name><o:p></o:p></name>
<o:p></o:p>
<o:p></o:p>
<o:p></o:p>
第四步,配制文件,我们写好了所有的代码后,就可以进行配制了,配制文件如下
- xml version="1.0"?>
- "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
- <faces-config>
- <component>
- <description>组件的配制description>
- <component-type>dinner.Clobcomponent-type>
- <component-class>
- dinner.view.jsf.uicomponent.OutputClobComponent
- component-class>
- component>
- <render-kit>
- <description>渲染器的配制description>
- <renderer>
- <component-family>dinner.Clobcomponent-family>
- <renderer-type>dinner.Clobrenderer-type>
- <renderer-class>
- dinner.view.jsf.uicomponent.OutputClobRender
- renderer-class>
- renderer>
- render-kit>
- faces-config>
<o:p></o:p>
<o:p></o:p>
<o:p></o:p>
<o:p></o:p>
<o:p></o:p>
<o:p></o:p>
<o:p></o:p>
<o:p> </o:p>
在这里,需要注意的事,组件和渲染器的component-family,renderer-type,component-type必须要以代码中写的返回值是一样的。<o:p></o:p>
<o:p> </o:p>
到这里一个简单的组件就完成的,所以如果选择好继承类的话,写一个组件还是挺简单的。<o:p></o:p>
<o:p></o:p>