理解JSF组件开发中的component-family和renderer-type

本文详细解析了JSF自定义组件的开发流程,包括组件类、渲染类和标签类的作用,以及如何通过配置文件实现组件与不同样式的关联。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开发一个JSF自定义组件一般需要开发三个类:组件类(Component,这代表了组件的模型)、渲染类(Renderer,负责显示视图)和标签类(Tag,负责引用组件类和渲染类),别外还需要两个对应的文件,一个对Tag的时行描述的TLD文件和一个对组件的配置文件。关于如何开发JSF自定义组件已经有很多好文章和图书,这里就不多做介绍了,可以参考《Pro JSF And AJAX》这本书,我觉得讲得很不错。由于JSF中巧妙地将组件模型和视图显示分离开来,这样同一个组件模型可以以不同的样式显示,换句话说,不同的显示视图可以重用同一个模型。这篇文章中,主要是想说明这是如何实现的。我们先从JSF自定义组件的配置文件说起,下面是我的faces-config.xml中的一段:

xml 代码
 
  1. <render-kit>  
  2.     <renderer>  
  3.       <component-family>com.yanhua.YhComponent</component-family>  
  4.       <renderer-type>com.yanhua.YhRenderer1</renderer-type>  
  5.       <renderer-class>com.yanhua.YhRenderer1</renderer-class>  
  6.     </renderer>  
  7.   
  8.     <renderer>  
  9.       <component-family>com.yanhua.YhComponent</component-family>  
  10.       <renderer-type>com.yanhua.YhRenderer2</renderer-type>  
  11.       <renderer-class>com.yanhua.YhRenderer2</renderer-class>  
  12.     </renderer>  
  13. </render-kit>  


这段配置比较好理解,我定义了两个Renderer,它们具有相同的component-family,把有不同的renderer-type,当然也指向不同的Renderer类,也就是说,一个component-family和renderer-type的组合才能确定一个Renderer类。比如一个Component对象要显示的时候,它首先要得到一个Renderer,然后调用Renderer的方法来显示,请看javax.faces.component.UIComponentBase的renderStart这个方法,在显示时会先调用这个方法:

java 代码

 

 
  1.   public void encodeBegin(FacesContext context)  
  2.     throws IOException  
  3.   {  
  4.     if (context == null)  
  5.       throw new NullPointerException();  
  6.   
  7.     if (! isRendered())  
  8.       return;  
  9.   
  10.     Renderer renderer = getRenderer(context);  
  11.   
  12.     if (renderer != null)  
  13.       renderer.encodeBegin(context, this);  
  14.   }  
  15.   
  16.   @Override  
  17.   protected Renderer getRenderer(FacesContext context)  
  18.   {  
  19.     RenderKit renderKit = context.getRenderKit();  
  20.   
  21.     if (renderKit != null)  
  22.       return renderKit.getRenderer(getFamily(), getRendererType());  
  23.     else  
  24.       return null;  
  25.   } 

 

>>UIComponentBase.java

我们在自己的Component(继承自UIComponentBase)类中只重写getFamily方法:

java 代码

 

 
  1. public String getFamily()   
  2. {  
  3.         return "com.yanhua.YhComponent";  
  4. }  

 

而getRendererType方法我们沿用父类提供的就可以了:

java 代码

 

 
  1. public String getRendererType()  
  2. {  
  3.       if (_rendererType != nullreturn _rendererType;  
  4.           ValueBinding vb = getValueBinding("rendererType");  
  5.       return vb != null ? (String)vb.getValue(getFacesContext()) : null;  
  6. }  

 


那_rendererType的具体值是在什么时候设置进去的呢?这就要看前面提到的Tag类了,我们来看看UIComponentTag这个类的setProperties方法:
UIComponentTag

可以看出这里它给Component的_rendererType赋了值。我们只要在自己的Tag类(继承自UIComponentTag)中重写getRendererType方法就可以了,比如我们写两个Tag类Tag1中的代码是这样的:

java 代码

 

  1. protected void setProperties(UIComponent component)  
  2.   {  
  3.         if (getRendererType() != null)  
  4.         {  
  5.             _componentInstance.setRendererType(getRendererType());  
  6.         }  
  7.   
  8.         if (_rendered != null)  
  9.         {  
  10.             if (isValueReference(_rendered))  
  11.             {  
  12.                 ValueBinding vb = getFacesContext().getApplication().createValueBinding(_rendered);  
  13.                 component.setValueBinding("rendered", vb);  
  14.             } else  
  15.             {  
  16.                 boolean b = Boolean.valueOf(_rendered).booleanValue();  
  17.                 component.setRendered(b);  
  18.             }  
  19.         }  
  20.   }  

 

>>

java 代码

 

 
  1. public String getRendererType()   
  2. {  
  3.         return "com.yanhua.YhRenderer1";  
  4. }  

 

Tag2中的代码是这样的:

java 代码

 

 
  1. public String getRendererType()     
  2. {    
  3.        return "com.yanhua.YhRenderer2";    
  4. }    

 

这样,我们在JSP页面中加入两个标签:

xml 代码

 

 
  1. <yh:tag1>.......</yh:tag1>    
  2.   
  3. <yh:tag2>.......</yh:tag2>  

 


这样,这们两个标签会以不同的样式显示,但它们重用了同一个Component类。不知道我说清楚了没有,不清楚的话,把文章从下往上倒着看一篇应该就知道整个的调用过程了。*^_^*

 

 

 

 

 

 

 

http://www.javaeye.com/topic/47830

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值