编写JSF用户自定义UI组件(之五)

【续前。。。。。。】

九、步骤三:编写标签库描述符

前文多次提到,用户在JSP文件中写入<x:repeatText...>这样的标签,当JSP引擎读到这个标签时,将翻译为对的标签处理器类 StrRepeatTag的调用。我们的问题是,标签名称repeatText和标签处理器类名称StrRepeatTag完全不同,JSP引擎是如何正确地找到与标签名称对应的标签处理器类的呢?这正是标签描述库要做的。

标签库描述符的后缀为tld,实际上是一个xml文件,其中定义了与标签名对应的标签处理器类名。程序清单 9所示是一号组件的标签描述符的部分内容:

程序清单 9 一号组件的标签描述符文件的内容节选

 

   <tag>
       <name>repeatText</name>
       <tag-class>customcomponent1.StrRepeatTag</tag-class>
       <attribute>
           <name>text</name>
       </attribute>
       <attribute>
           <name>number</name>
       </attribute>
   </tag>
 

我们感兴趣的内容被在<tag>元素内,其中可见包含在<name>元素内的标签名repeatText和<tag- class>元素内的标签处理器类名customcomponent1.StrRepeatTag。标签和标签处理器类之间的对应关系就是这样建立的。

除了给标签和标签处理器类配对外,标签库描述符还用来定义标签的属性,例如上面例子用<attribute>元素分别定义了text和number两个属性。这里的定义主要是供JSP引擎使用的。JSP引擎将根据标签属性定义对用户在JSP文件中写入的内容进行格式检查,如果用户写入既非text亦非number的属性名,则JSP引擎将报错。

NetBeans对标签库描述符的编写提供了工具支持。我们可以用如下步骤为一号组件创建标签库描述符:

1.    在NetBeans新建一个文件,“类别”选择“Web”,“文件类型”选择“标记库描述符”;
2.    NetBeans打开“新建标记库描述符”对话框,在其中输入文件名如mytld;
3.    在根元素<taglib>内添加一个<tag>元素;
4.    在<tag>元素内,用<name>元素定义标签名,用<tag-class>元素定义标签处理器类,用<attribute>元素定义标签属性。

图 9显示了NetBeans的“新建标记库描述符”对话框。图中有一个值得注意的点是URI。当我们有许多来自不同厂商的标签库描述符文件时,这些文件可能包含有相同名称的标签,甚至连标签库描述符文件本身的名称都可能相同(当然,放在不同的目录或者Jar文件中)为每个标签库描述符定义一个唯一的URI,可以用来区分不同的标签库描述符。因此,URI必须是唯一的,通常用厂商的域名来命名,例如http://java.sun.com/jsf/core或者http://jsf.madihe.com/my/custom等等。我们的例子中,只有一个标签库,因此,我们接受NetBeans给出的默认 URI即/WEB-INF/tlds/mytld,不做修改。
 



 

图 9 NetBeans的新建标记库描述符对话框


NetBeans中一号组件标签库描述符mytld.tld的完整代码如图 10所示。图中我们折叠了所有注释内容。




 

图 10 NetBeans中一号组件标签库描述符mytld.tld的完整代码



十、步骤四:配置自定义UI组件

经过前面三个步骤,可以说JSF自定义UI组件的编写过程已经基本完成,现在我们有一个组件类StrRepeat.java用来定义一号组件的特征和行为,一个标签处理器类StrRepeatTag.java用来处理相应的JSP标签,还有一个标签库描述符mytld.tld用来建立JSP标签<x:repeatText>和标签处理器类StrRepeatTag之间的联系,当JSP引擎遇到<x:repeatText>这样的标签时,将会其翻译为StrRepeatTag类的实例化代码。

但是StrRepeatTag并不是我们所需要的,因为UI逻辑不在StrRepeatTag类上,而是在组件类StrRepeat上,只有这个类才包含了我们定义的UI逻辑,即在其方法encodeEnd()中以指定的次数重复输出指定字符串。

可见,标签处理器类StrRepeatTag不是我们的最终目的,组件类StrRepeat才是。因此,在StrRepeatTag的父类 UIComponentELTag中,包含了实例化组件类并给其赋值的代码。StrRepeatTag类继承了这些代码,所以我们不必自己动手编写。

那么,UIComponentELTag是如何知道应该实例化哪个类的呢?记得上文我们曾经提到StrRepeatTag类覆盖了父类的 getComponentType()的方法,这个方法简单地返回一个称为“组件类型”的字符串。这个组件类型字符串正是定位组件类的依据。

图 11以一号组件为例,示出了JSP标签、标签处理器类、组件类是如何通过标签库描述符和组件类型进行关联的。从图中可见,标签库描述符“粘合”了JSP标签和标签处理器类,而组件类型则“粘合”了标签处理器类和组件类,这样,我们在JSP页面上写下的标签<x:repeatText>最终变成了组件类StrRepeat的一个实例。



 

图 11 标签库描述符和组件类型的“粘合”作用


在 JSF中,UI组件的生成是由一个专门的类负责的,这个类称为Application类。UIComponetELTag从 getComponentType()方法中获得组件类型,以这个组件类型为参数调用Application类的createComponent()方法。知道组件类型后,createCompnent()方法在一个配置文件中查询组件类型对应的组件类,并且实例化该组件类。

所谓配置自定义UI组件,实际上就是编写这个配置文件,在其中建立组件类型和组件类的关联关系,而这个配置文件不是别的,就是我们所熟知的JSF应用的配置文件,其缺省名称为faces-config.xml。配置的方法非常简单,只是在faces-config.xml文件中加入<component>元素而已。

图 12以一号组件为例,示出了如何在faces-config.xml中配置自定义UI组件。图中高亮部分即为我们加入的<component>元素,它包括<component-type>和<component-class>两个子元素,<component-type>用来定义组件类型,而<component-class>用来定义对应的组件类。本例中,组件类型为MyComponentType,组件类为customcomponent1.StrRepeat。注意,组件类必须包括完整的包名。




 

图 12 在faces-config.xml中配置自定义UI组件



在NetBeans中,配置一号组件的步骤如下:
1.    打开faces-config.xml,并且切换到XML显示格式;
2.    将程序清单 10所示的代码添加到faces-config.xml中,置于根元素<faces-config>之下;

程序清单 10 在faces-config.xml中用<component>元素配置自定义UI组件

    <component>
        <component-type>MyComponentType</component-type>
        <component-class>customcomponent1.StrRepeat</component-class>
    </component>
 

十一、运行一号组件

我们已经了解了一号组件功能,完成了一号组件的编码,并且知道了如何引用一号组件。现在,我们试着编写一个简单的JSF应用,让这个应用包含一号组件,并运行之,以便对编写和使用JSF自定义UI组件产生一个完整的认识,

下面以NetBeans 6.0.1为例,列出编程和运行步骤。NetBeans的其他版本如6.1等,也是类似的:

1.    创建一个“Web应用程序”项目
a)    将项目命名为CustomComponent1;
b)    选择GlassFish为应用服务器;
c)    选择Java EE 5为Java EE版本;
d)    选择“Visual Web JavaServer Faces”为框架;
2.    创建组件类
a)    创建一个Java类,命名为StrRepeat,放在customcomponent1包中,修改其声明,使继承UIComponentBase类;
b)    定义text和number属性及其getter和setter方法;
c)    覆盖父类的encodeEnd()方法;
代码如程序清单 3和图 6所示
3.    创建标签处理器类
a)    创建一个Java类,命名为StrRepeatTag,放在customcomponent1包中,修改其声明,使继承UIComponentELTag类;
b)    创建text属性和number属性,以及它们的getter和setter方法;
c)    实现getComponentType()方法,使返回字符串“MyComponentType”;
d)    实现getRendererType()方法,使返回null;
e)    覆盖setProperties()方法。
代码如程序清单 8和图 8所示。
4.    创建标签库描述符
a)    在NetBeans中新建一个文件,“类别”选择“Web”,“文件类型”选择“标记库描述符”;
b)    NetBeans打开“新建标记库描述符”对话框,在其中输入文件名如mytld;
c)    在根元素<taglib>内添加一个<tag>元素;
d)    在<tag>元素内,用<name>元素定义标签名,用<tag-class>元素定义标签处理器类,用<attribute>元素定义标签属性。
代码如图 10所示
5.    配置自定义UI组件
a)    打开faces-config.xml,并且切换到XML显示格式;
b)    将程序清单 10所示的代码添加到faces-config.xml中,置于根元素<faces-config>之下;
faces-config.xml的完整代码如图 13所示(折叠了managed-bean的定义),其中高亮部分为自定义UI组件的定义。




 

图 13 NetBeans中faces-config.xml的完整代码


6.    编写JSF页面
a)    打开NetBeans自动创建Page1页面,并切换到JSP显示方式;
b)    在<jsp:root>标签内加入前缀x的定义xmlns:x="/WEB-INF/tlds/mytld"
c)    在<webuijsf:form>标签之下加入<x:repeatText text="asdadf" number="3"/>
Page1页面完整代码如图 14所示,其中我们添加的内容用圆圈标了出来。




 

图 14 在Page1页面内定义前缀和引用自定义UI组件


7.    运行程序
a)    按F6运行程序;
b)    在浏览器上,可以观察到一号组件的输出,如图 3所示。

十二、范例程序代码下载

如果不愿意花费时间自己编写一号组件的相关代码,你可以下载完整的范例程序代码,并在你的NetBeans中作为项目打开、查看和运行它。

关于开发环境的配置以及范例程序的解压和运行,请参阅《JSF Web应用开发实战》一书的第12章,不再赘述。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值