Java Server Faces (JSF) 页面转换与验证(一)

梦想的初衷 提交于 2019-12-02 17:22:18

由于primefaces在国内使用的并不是太多,因此,国内对jsf做系统、详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的,很可能会误导使用者。

相对来说,看国内的那些仅仅是翻译过来的文章或书籍不如直接看国外的官方文档或资料来的实在,在我讲述jsf页面中如何使用js调用后台bean方法之前,先给大家说几个国外的资料。在primefaces官方网站上,你可以搜索到几乎所有你需要的东西,primefaces官网为:http://www.primefaces.org/showcase/index.xhtml 如过觉得自己英语不好的童鞋,可以前往primefaces国内镜像网站查阅资料: http://www.primefaces.cn/ ,只是国内的这个网站正在翻译中,有些东西还不完善;如果有想细致的了解primefaces的朋友,还可以下载primefaces的官方文档,最新的官方文档为5.2,全英文,我在这里给大家提供我下载好的primefaces官方文档:http://pan.baidu.com/s/1mg3i9Ry ,在这个文档里你可以通过他们的示例来组合出来很多有趣的东西。另外我在淘宝上发现了Primefaces官方的JSF框架,官方售价300RMB,淘宝售价才五元,大家可以前去学习:https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-12555052969.2.nPXnNz&id=523880497056

在本文中,我们将介绍  JSF 转换和验证框架的概念,它比您所想的要容易使用得多,也灵活得多。

首先我们将介绍应用于 JSF 生命周期的转换和验证过程,然后展示一个简单的 JSF 应用程序中 的默认转换和验证过程。接着将展示如何创建和插入自定义的实现,以应对要求更高的场景。正如   Rick 在以前的文章中所说的,我们会理论与实践并重,先介绍概念,再用一个实际 例子说明这些概念的应用。示例应用程序将涵盖大多数转换和验证用例,虽然只是初级的。

注意,示例应用程序的默认编译环境是 Maven,不过 , 还提供了一个 Ant 脚本。 可以单击本页顶部或者底部的  Code图标下载示例源代码。为了简便起见,您会发现,该例子的设置与上一篇文章中的一样。 关于构建环境配置的更多说明,包括在 Ant 环境中而不是在 Maven 环境中编译和运行 示例应用程序的说明,请参阅 参考资料。

转换和验证

虽然在 JSF Web 应用程序中使用转换和验证不一定要理解 JavaServer  Faces 生命周期的基础知识,但是在深入转换和验证内容之前,最好对一些基本知识做一回顾。 此外,掌握一点 JSF 生命周期技巧可以极大地帮助简化 Web 应用程序的开发 工作。还有助于更好地理解 JSF 的可插入能力。

下面的图片描绘了我们所说的“基本 JSF 生命周期”。   基本是在暗示这只是一个典型的处理所提交表单值的请求 - 响应(request-and-response)场景。

显然,不同的场景对这里重点描述的生命周期有不同的影响。我们将在 本文稍后介绍其中一些场景。现在,只需要注意转换和验证过程发生在 应用请求值处理验证呈现响应阶段即可。

我们将在稍后介绍为什么转换和验证会在这些阶段出现,但是首先让我们 澄清一个更基本的问题:转换是什么?简单地说,转换是确保数据拥有正确的对象或者类型的过程。下面是两个典型的转换:

  • 字符串值可以转换为 java.util.Date
  • 字符串值可以转换为 Float。

    至于 验证,它用于确保数据包含所期望的内容。下面是两个 典型的验证:

  • java.util.Date 的格式为 MM/yyyy。

  • Float 在 1.0 和 100.0 之间。

关注生命周期阶段

转换和验证的主要目的是确保在更新模型数据之前已经经过了正确的 无害处理。之后,当需要调用应用程序方法用这些些数据实际 做一些事情时, 就可以有把握地假定模型的某些状态。转换和验证使您可以侧重于业务逻辑,而不是侧重于对输入数据进行繁琐的资格认定,比如 null 检验、长度限定、范围边界,等等。

因此,在 更新模型数据生命周期阶段中,在组件数据被绑定到 backing bean 模型 之前 进行转换和验证处理是有道理的。正如图 1 所示,转换发生在应用请求值阶段,而验证发生在 处理验证阶段。下图突出显示了这些阶段。

关于 immediate 属性

注意,图 2 中描绘的转换和验证过程表示了将 UIInput组件的  immediate属性设置为 false时的应用程序流程。 如果这个属性设置为 true,那么转换和验证会发生在生命周期更早的时期,即应用请求值阶段(参见图 3)。对使用 immediate 属性的详细讨论超出了本文的范围,但是在某些情况下,比如管理动态清单(可能您还记得,本系列的上一篇文章中曾介绍过),它很有用,它甚至可以绕过验证(在与 UICommand组件结合使用时)。能想像一个 需要完全绕过验证的应用程序吗?

下面的图片内容展示了当 immediate属性设置为 true时, 在 JSF 应用程序生命周期中的哪些地方进行转换和验证。

实际的例子

下面,我们将用一个示例应用程序展示所讨论的概念。本月的示例应用程序 将展示 JSF 的转换和验证能力。记住,这个示例应用程序非常简单,没有追求一些不必要的面面俱到: 无论如何,我们的目的不是构建一个在真实世界中使用的应用程序!这个示例应用程序 将展示以下几点:

  • 使用标准 JSF 转换器转换表单字段数据。

  • 使用标准 JSF 验证组件验证表单字段数据。

  • 如何编写自定义转换器和验证器。

  • 如何在 faces-config.xml 文件中注册自定义转换器和验证器。

  • 如何定制默认错误消息。

这个示例应用程序是一个简单的用户注册表单。我们的目标是收集用户数据,比如 姓名、年龄、电子邮箱地址和电话号码。然后,我们将展示如何利用 JSF 转换和验证 确保收集的数据对于模型是适合的。

这个应用程序使用了三个 JSP 页:

  • index.jsp 将用户定向到 UserRegistration.jsp。

  • UserRegistration.jsp 包含应用程序的表单字段。

  • results.jsp 通知应用程序用户已经注册。

我们将首先分析编写 JSF 转换过程的选择。

JSF 转换

如前所述,转换是确保数据对象或者类型正确的一个过程,因此,我们将字符串值 转换为其他类型,比如 Date对象、基本浮点型或者  Float对象。可以使用自带的转换器,也可以编写 自定义的转换器。

JSF 提供了许多标准数据转换器。也可以通过实现 Converter接口插入 自定义转换器,但是这些将在后面进行介绍。下表显示了 JSF 进行简单数据转换所使用的转换器 id及其对应的实现类。大多数数据转换是自动发生的。

javax.faces.BigDecimal javax.faces.convert.BigDecimalConverter
javax.faces.BigInteger javax.faces.convert.BigIntegerConverter
javax.faces.Boolean javax.faces.convert.BooleanConverter
javax.faces.Byte javax.faces.convert.ByteConverter
javax.faces.Character javax.faces.convert.CharacterConverter
javax.faces.DateTime javax.faces.convert.DateTimeConverter
javax.faces.Double javax.faces.convert.DoubleConverter
javax.faces.Float javax.faces.convert.FloatConverter

下图展示了用户年龄的默认转换。

JSF 标签配置如下:

  <h:inputText id="age" value="#{UserRegistration.user.age}"/>

各种情况的转换器

UserRegistration.user.age表示一个值绑定属性,它的类型为  int。对于基本型或者 BigInteger/   BigDecimal的绑定,JSF 选择了标准转换器。不过,还可以通过  <f:converter/>标签,利用一个特定的转换器来增加粒度,如下所示。

 <h:inputText id="age" value="#{UserRegistration.user.age}"> 

             <f:converter id="javax.faces.Short"/> 

 </h:inputText>

在下图中,可以看到 JSF 使用标准转换器的场景。在这种情况下,虽然 年龄实际上是一个有效的整数,但转换仍然会失败,因为该值不是短整型的。

选择日期格式样式

尽管在默认情况下,JSF 可以很好地处理基本型及类似的类型,但是在处理 日期数据时,必须指定转换标签 <f:convertDateTime/>。 这个标签基于  java.text包,并使用短、长和自定义样式。下面是一 个例子:

 <!-- UserRegistration.jsp --> 
 <h:inputText id="birthDate" value="#{UserRegistration.user.birthDate}"> 
             <f:convertDateTime pattern="MM/yyyy"/> 
 </h:inputText>

这个例子展示了如何用  <f:convertDateTime/>确保用户的生日可以转换为 格式为 MM/yyyy(月 / 年)的日期对象。请参阅 JSF 的 java.text.SimpleDataFormat (在参考资料中),以获取模式列表。

其他样式

除了可以转换日期和时间格式外,JSF 还 提供了处理像百分数或者货币数据这类值的特殊转换器。 这个转换器处理分组(如逗号)、小数、货币符号等。例如, 以下 <f:convertNumber/> 的用法就是处理货币的一种技巧:

 <!-- UserRegistration.jsp --> 
 <h:inputText id="salary" value="#{UserRegistration.user.salary}"> 
             <f:convertNumber maxFractionDigits="2"
                       groupingUsed="true"
                       currencySymbol="$"
                       maxIntegerDigits="7"
                       type="currency"/> 
 </h:inputText>

在下图中,可以看到一些格式编排不正确的货币数据,以及所导致的转换错误。

自定义转换

如果需要将字段数据转换为特定于应用程序的值对象,则需要自定义数据转换, 如下面例子所示:

  • String 转换为 PhoneNumber 对象 (PhoneNumber.areaCode、PhoneNumber.prefix、 ...)。

  • String 转换为 Name 对象 (Name.first、Name.last)。

  • String 转换为 ProductCode 对象 (ProductCode.partNum、ProductCode.rev、 ...)。

要创建自定义转换器,必须完成以步骤:

  1. 实现 Converter接口(也就是   javax.faxes.convert.Converter)。

  2. 实现 getAsObject方法,它将一个字段(字符串) 转换为一个对象(例如,PhoneNumber)。

  3. 实现 getAsString方法,它将一个对象 (如 PhoneNumber)转换为一个字符串。

  4. Faces 上下文中注册自定义转换器。

  5. 用  <f:converter/>标签在 JSP 中插入这个转换器。

您可以自己看到如何在 JSF 应用程序生命周期中加入这些步骤。 在下图 中,JSF 在应用请求值阶段调用自定义转换器的 getAsObject方法。 转换器必须在这里将请求字符串转换为所需的对象类型,然后返回这个对象,将它存储在相应的 JSF 组件中。 如果该值被返回呈现在视图中,那么 JSF 将在呈现响应阶段调用 getAsString方法。 这意味着转换器还要负责将对象数据转换回字符串表示形式。

创建自定义转换器

我将在下一篇博客中国使用一个案例分析来展示 Converter 接口、getAsObjectgetAsString方法的实现,同时还将展示如何在 Faces上下文中注册这个转换器。


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!