`
麻地河
  • 浏览: 9827 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
社区版块
存档分类
最新评论

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

阅读更多

【续前。。。。。。】

八、步骤二:编写标签处理器类

UI组件类不同于普通Java类的地方是,它不是在Java代码中被引用,而是在JSP文件中。在JSP文件中,我们不能通过new操作符实例化UI组件类,只能通过JSP标签引用和实例化UI组件类。

前文介绍过如何引用一号组件,即在JSP文件中写入类似这样的标签即可:

<x:repeatText text="Hello world!" number="3">


当 JSP引擎读到这个标签时,它会把x:repeatText翻译为对某个类的调用,这个类就是所谓的标签处理器类tag handler。JSP引擎会将组件类的一个实例传递给标签处理器类,标签处理器类的功能是给这个组件类实例的各个属性赋值,值的来源就是标签中的 text="Hello world!" number="3"。

可见,JSP引擎和标签处理器类配合工作,可以实现类似于Java代码 中实例化一个类并给类的属性赋值的功能。我们在JSP文件中写下<x:repeatText text="Hello world!" number="3">,实际上就相当于实例化一号组件类并给其text和number分别赋值“Hello world!”和“3”。图 7示出了JSP标签和普通Java代码的类比。


 
图 7 JSP标签和普通Java代码的类比

 

也许你已经留意到图 7中标签名repeatText和组件类名StrRepeat之间的不同,它们是如何对应的,我们将在后文解释。

理解了标签处理器类的作用后,我们就很容易编写它的代码了。如同组件类StrRepeat可以继承UIComponentBase类一样,标签处理器类也可 以继承JSF框架提供的几个标签处理父类,以减少代码量。例如,一号组件的标签处理类可以继承UIComponentELTag类,如果我们将一号组件的 标签处理器类命名为StrRepeatTag,则其声明为:

public class StrRepeatTag extends UIComponentELTag{
    ...
}
 

标签处理器类的属性决定了我们允许用户在JSP文件中为自定义UI组件的哪些属性赋值。对于一号组件,我们允许用户在JSP标签中对一号组件的text和 number属性赋值,因此,StrRepeatTag类也必须有text和number这两个属性,用来接收用户在JSP标签中写入的值,然后转赋给一 号组件。这很容易,只需为StrRepeatTag类定义两个标准的JavaBeans属性即可,如程序清单 4所示。

程序清单 4 StrRepeatTag类的text和number属性

    private String text;
    public String getText() { return text; }
    public void setText(String text) { this.text = text; }

    private int number;
    public int getNumber() { return number; }
    public void setNumber(int number) { this.number = number; }
 

读者不难发现,这部分代码和一号组件类StrRepeat的(见程序清单 1)完全一样,甚至连属性名称都相同。当然,这不是强制要求,标签处理器类和相应的组件类的属性可以不同名,个数也可以不同,如果你无需允许用户在JSP标签中给组件类的所有属性赋值。

标签处理器类有几个方法,我们逐一说明:

1.    返回组件类型的方法getComponentType()(参见程序清单 5)

程序清单 5 标签处理器类StrRepeatTag的getComponentType()方法代码

    @Override
    public String getComponentType() {
        return "MyComponentType";
    }

 
这个方法返回一个称被为“组件类型”的字符串。组件类型决定了标签处理器类和组件类之间的对应关系,例如,当JSP引擎碰 到<x:repeatText.../>这样的标签时,之所以能够正确地判断出这是与StrRepeat组件类相对应的一个标签,正是由于“ 组件类型”字符串起着牵线搭桥的作用。具体的对应方法,后文有更详细的说明。

父类UIComponentELTag中的getComponentType()方法是抽象的,因此必须在子类中实现它。本例中,我们返回的组件类型为MyComponentType,如程序清单 5所示。

2.    返回呈现器类型的方法getRendererType()(参见程序清单 6)

程序清单 6标签处理器类StrRepeatTag的getRendererType()方法代码

    @Override
    public String getRendererType() {
        return null;
        //throw new UnsupportedOperationException("Not supported yet.");
    }
 

呈现器是一种专门负责向http响应输出组件内容的类。JSF允许组件类自己输出自己的内容,也允许它假手于人,即交给与之对应的呈现器类来输出。这个方法 返回的呈现器类型,正是用来供JSF框架选择合适的呈现器类的。由于一号组件是自己负责输出,不需要呈现器类,因此,我们让这个方法简单地返回一个 null,即告诉JSF框架,一号组件没有对应的呈现器类。

父类UIComponentELTag中的getRendererType()方法是抽象的,因此必须在子类中实现它。

3.    给组件类实例赋值的方法setProperties()

程序清单 7标签处理器类StrRepeatTag的setProperties()方法代码

    @Override
    protected void setProperties(UIComponent component) {
        super.setProperties(component);
        component.getAttributes().put("text", this.getText());
        component.getAttributes().put("number", this.getNumber());
    }
 

我们已在前面提到,用户可以通过JSP标签给组件类实例的属性赋值,setProperties()方法实现的正是这个功能。其入口参数component 是对应的组件类的实例,给实例赋值的方法有点特殊,不是直接调用相应属性的setter方法(如我们通常所做的那样),而是通过给一个Map中添加名值对 来实现的。这个Map的内容是由JSF的UI组件自己负责维护的,其中包含了一些名值对,“名”即为其各个属性的名称,“值”则是该属性的取值。调用组件 的getAttributes()方法可以获得这个Map,往其中put一个名值对,就相当于给一个指定名称的属性赋值。例如,代码 put("text", this.getText())给一号组件实例的text属性赋值,值是通过this.getText()方法获得的(这里的this代表标签处理器类的 实例本身),也就是用户在标签中输入的“Hello world!”。

父类UIComponentELTag中已经实现setProperties()方法,子类StrRepeatTag覆盖这个方法,因此必须在方法的最前面调用父类的实现,即super.setProperties(component)。

StrRepeatTag类的完整代码(省略了package和import语句)如所示。

程序清单 8 一号组件的标签处理器类StrRepeatTag的完整代码

public class StrRepeatTag extends UIComponentELTag{

    @Override
    public String getComponentType() {
        return "MyComponentType";
    }

    @Override
    public String getRendererType() {
        return null;
        //throw new UnsupportedOperationException("Not supported yet.");
    }
   
    @Override
    protected void setProperties(UIComponent component) {
        super.setProperties(component);
        component.getAttributes().put("text", this.getText());
        component.getAttributes().put("number", this.getNumber());
    }
   
    private String text;
    public String getText() { return text; }
    public void setText(String text) { this.text = text; }

    private int number;
    public int getNumber() { return number; }
    public void setNumber(int number) { this.number = number; }
}
 

在NetBeans中,为一号组件编写标签处理器类StrRepeatTag的步骤如下:

1.    创建一个Java类,命名为StrRepeatTag,放在customcomponent1包中,修改其声明,使继承UIComponentELTag类;
2.    创建text属性和number属性,以及它们的getter和setter方法;
3.    实现getComponentType()方法;
4.    实现getRendererType()方法;
5.    覆盖setProperties()方法。

图 8是NetBeans中的StrRepeatTag类代码。
 



 
图 8 NetBeans中一号组的标签处理器类StrRepeatTag的代码

 

【待续。。。。。。】

 

  • 大小: 3.4 KB
  • 大小: 28.6 KB
2
0
分享到:
评论

相关推荐

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

    NULL 博文链接:https://madihe-126-com.iteye.com/blog/266276

    JBoss Seam 工作原理、seam和hibernate的范例、RESTFul的seam、seam-gen起步、seam组件、配置组件、jsf,jboss、标签、PDF、注解等等

    Seam - 语境相关的组件[满江红20071230]............................................................................................................................ 1 Java EE 框架...........................

    java开源包1

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包11

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包2

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包3

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包6

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包5

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包10

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包4

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包8

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包7

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包9

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包101

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    Java资源包01

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    JAVA上百实例源码以及开源项目

     Java编写的山寨QQ,多人聊天+用户在线,程序分服务端和客户端,典型C/S结构,  当用户发送第一次请求的时候,验证用户登录,创建一个该qq号和服务器端保持通讯连接得线程,启动该通讯线程,通讯完毕,关闭Scoket...

    JAVA上百实例源码以及开源项目源代码

     Java编写的山寨QQ,多人聊天+用户在线,程序分服务端和客户端,典型C/S结构,  当用户发送第一次请求的时候,验证用户登录,创建一个该qq号和服务器端保持通讯连接得线程,启动该通讯线程,通讯完毕,关闭Scoket...

    Spring攻略(第二版 中文高清版).part2

    1.14 从Classpath中扫描组件 50 1.14.1 问题 50 1.14.2 解决方案 51 1.14.3 工作原理 51 1.15 小结 56 第2章 高级Spring IoC容器 57 2.1 调用静态工厂方法创建Bean 57 2.1.1 问题 57 2.1.2 解决...

    Spring攻略(第二版 中文高清版).part1

    1.14 从Classpath中扫描组件 50 1.14.1 问题 50 1.14.2 解决方案 51 1.14.3 工作原理 51 1.15 小结 56 第2章 高级Spring IoC容器 57 2.1 调用静态工厂方法创建Bean 57 2.1.1 问题 57 2.1.2 解决...

Global site tag (gtag.js) - Google Analytics