JSF Converter使用总结

PrimeFaces4,5的AutoComplete、SelectOneMenu等在下拉菜单中除了显示单纯的文字列表外,还可以分多列显示图片等内容,效果上比OS自带的控件更绚了,但使用上并不复杂,将String的List数据更换成POJO的List,再自定义一个Converter就行了。

     Converter并不是PrimeFaces定义的,属于JSF规范。在JavaEE的文档[3]中,对Converter的介绍是“Converters are used to convert data that is received from the input components.” ,需要这个东西的原因是JSF等Web层和普通GUI一样,用户输入的内容都是作为字符串来接收和显示的,但是在程序内部存储的变量则可能是Integer,Float,Date等等类型,需要进行类型转换。以往这些转换是由应用设计人员自己编码进行的,但新的GUI框架中,这部分转换基本都交给专门的功能类来处理了。

JSF2.0中,这个转换工作是由Converter类来完成的,JavaEE6.0已经实现了一部分数据类型的Converter,位于javax.faces.convert 包内:
  • BigDecimalConverter
  • BigIntegerConverter
  • BooleanConverter
  • ByteConverter
  • CharacterConverter
  • DateTimeConverter
  • DoubleConverter
  • FloatConverter
  • IntegerConverter
  • LongConverter
  • NumberConverter
  • ShortConverter

对于只有一个属性的简单对象,如数值或者字符串、日期等,界面所输入和显示的字符串是可以完全包含内部存储变量的值,但对于包含多个属性的对象,通常是不能和表示形式完全等价转换的,比如在界面上显示一个人员信息列表,只显示其姓名,但为防止重名,通常是使用ID等唯一编号来表示的,需要定义一个特定的Converter来进行编号和对象之间的相互转换。

比如PF4文档中的SelectOneMenu的例子:


<p:selectOneMenu value="#{menuBean.selectedPlayer}" converter="player" var="p">
    <f:selectItem itemLabel="Select One" itemValue="" />
    <f:selectItems value="#{menuBean.players}" var="player"
        itemLabel="#{player.name}" itemValue="#{player}"/>
    <p:column>
        <p:graphicImage value="/images/barca/#{p.photo}" width="40" height="50"/>
    </p:column>
    <p:column>
        #{p.name} - #{p.number}
    </p:column>
</p:selectOneMenu>

显示效果如下图:

在JSF页面代码中,选中的对象是需要转换为一个字符串形式来传递给后台的(可以看一下JSF运行生成的HTML源代码),所以每个对象要有一个字符串表示形式,同样该字符串表示形式也要能转换会对象。
JSF中的Faces转换器都必须实现接口javax.faces.convert.Converter ,该接口定义了两个方法:
public Object getAsObject(FacesContext context, UIComponent component, String value)
public String getAsString(FacesContext context, UIComponent component, Object value)
这两个方法所作的工作正好相反,一个是把String类型的value转换为Object类型,一个是把Object类型转换为String形式,分别用于处理输入和生成显示用的HTML代码。

Converter的使用和实现
     Converter的使用很简单,只要像上面的例子一样,在AutoComplete、SelectOneMenu等控件的converter属性里指定一下就行了,但其编写要稍微费点周折。和文档中的例子不同的是,实际项目中数据来源通常不是固定的,而是来自数据库等可变的数据。比如AutoComplete控件,下拉列表里的数据往往是根据输入内容从数据库里查询出来的,因此Converter要实现Object和String的转换,还需要获得数据库中的数据。
     比如以ID号作为员工对象转换为String的表示内容,则Object to String很简单,return ""+((Employee)obj).getId() 就行了,但String to Object就不那么简单了,员工姓名、性别等属性从何而来? 最直接的方法是也从数据库获取,还有一个方法是把刚才的下拉列表里的Employee List缓存在Session里,直接到里面查找。
     具体方式,从数据库获取的方法可以把Converter定义为JSF的托管Bean,给其配置到业务层或者持久层的访问接口。
     缓存在Session里的方式需要把AutoComplete对应的托管Bean在获取下拉列表的数据时,同时保存一份到Session里,比如把一个托管Bean生命周期定义为SessionScope,在里面存放数据,但同一个页面同时在多个窗口打开可能会有数据冲突。或者放在ViewScope的托管Bean里以避免?这种方式还没有经过验证,不确定会有什么问题。Converter从数据库获取Object的方式,为简单起见,可以把AutoComplete等控件对应的托管Bean实现为Converter,这样可以避免再配置一遍,不过结构上不太优雅,正式设计中还是不要这么做为好。


参考文献:
[1] PrimeFaces Users Guide 4.0 editn2
[2] Orical,JavaEE Tutorial6
[3] JavaServer Faces2.0, The Complete Reference


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值