最后更新时间:2007-03-27 关键字: jsf 自定义组件
自定义JSF组件
个人感觉,写一个jsf的组件比jsp的标签要复杂得多,因为jsp的标签,只有生成html代码的功能,jsf组件还有如增加事件,增加效验,返回用户反馈的值。等等!一个组件一般是分三部分,扩展UIComponent、定义标签、定义渲染器、。现在我就以一个最简单的例子,制作一个输出CLOB的组件来说明一下组件的建立的基本步骤
第一步:扩展UIComponent,他有一个实现类UIComponentBase,一般最基础的组件就是从这个类里扩展而来的,如果你在客户端显示Bean中的字段,你需要实现ValueHolder接口字段,如UIOutput组件;如果有返回值的话,还需要你实现EditableValueHolder接口,如UIInput组件。一般情况下,如果没有返回值就可以继承UIOutput组件,如果有返回值实现UIInput组件。这样,我们只要这样就可用以下代码就可以实现一个组件部分的编写
java 代码
- 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;
-
- }
-
- }
在构函数中的setRendererType(COMPONENT_FAMILY) 和getFamily 是指定用来生成HTML代码的渲染器,渲染器需要在faces-config.xml中进行配制,关于配制,在最后一步我会进行说明的。
第二步,定义渲染器。渲染器我们需要从Renderer类中继承,不过我们一般情况下会继承HtmlRenderer这个类,我们可以覆盖decode encodeBegin encodeChildren encodeEnd 来生成HTML,在这里,和自定义jsp标签的几个方法十分的相似,所以就不深入的说下去了,我们看一下例子。
java 代码
- 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);
-
- }
-
- }
因为例子很简单,所以只覆盖了encodeEnd方法。在这里,我们用到了RendererUtils类,在这个类里有很多的静态方法,如RendererUtils.getObjectValue是为了得到以这个控件绑定的字段。
第三步,定义标签,在这一步中我们需要继承UIComponentTag这个类,但在实际应用中,我们可以继承他的子类,比如在例子中我们就继承HtmlOutputTextTagBase。在标签类中,我们必须要覆盖getComponentType方法和getRendererType,来指定这个标签属于哪个组件和渲染器,这两个属性的返回值都应和配制文件指定的值相同。
java 代码
- 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";
-
- }
-
- }
在建立后tag类后,我们还需要做建一个tag文件,这样才能使用这个组件,在这里,和jsp自定义标签是一样的,所以也不再详述了,以下是代码
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>
第四步,配制文件,我们写好了所有的代码后,就可以进行配制了,配制文件如下
xml 代码
- 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>
在这里,需要注意的事,组件和渲染器的component-family,renderer-type,component-type必须要以代码中写的返回值是一样的。
到这里一个简单的组件就完成的,所以如果选择好继承类的话,写一个组件还是挺简单的。