简介
JSF 2的一个非常好的特性是它提供了对JSR-303 Bean验证器的内置支持。这意味着现在容器负责根据您基于注解的约束在多个应用层验证您的模型对象。看看一个简单的带有JSR-303注解的JSF管理Bean
import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; @ManagedBean @RequestScoped public class UserBean { @Size(min=3, max=12) private String name = null; @Pattern(regexp = "^[\\w\\-]([\\.\\w])+[\\w]+@([\\w\\-]+\\.)+[a-zA-Z]{2,4}$" , message="Bad email") private String email = null; @Min(value = 18) @Max(value = 99) private Integer age; ///... //Getters and Setters }
使用JSF 2,所有通过Bean验证注解添加的验证器都将注册到绑定到Bean属性的组件上,并在验证处理阶段触发。因此,您无需使用JSF标准验证标签(如f:validateLength或f:validateDoubleRange)或使用required属性来定义额外的验证器。但所有这些都仅在服务器端应用。在过去,您需要创建一些自定义客户端验证器,这些验证器与服务器端规则没有直接连接,但只是复制了该功能。这无疑导致了额外的维护和复杂性。
现在,随着RichFaces 4,我们为验证生态系统提供了最终的抽象层。RichFaces客户端验证特性(CSV缩写用于整个wiki页面和jiras)包括
- 几乎所有JSF和JSR-303验证器的JavaScript验证器实现。
- 将相应的客户端验证器注册到绑定到注解字段或使用f:validate*附加的组件上的机制。
- 添加了具有客户端对象的rich:message(s)组件,允许在客户端操作它们。用于添加/删除在客户端出现的消息。
- 扩展点,允许用户为其自定义服务器端验证器提供JavaScript实现(未来)。
使用方法
首先需要提到JSF和RichFaces使用Bean验证的常见需求。为了在JSF 2中使用它,您应该使用捆绑了JSR-303实现的JEE 6应用服务器。或者,如果您仅使用Tomcat或其他简单的servlet容器,请将validation-api jar和一些验证器提供者(例如hibernate-validator)添加到您的应用程序库中。
然后,您只需将新rich:validator行为添加到组件中,就可以开始使用客户端验证器。
<h:inputText value="#{userBean.name}"> <rich:validator/> </h:inputText>@Size
上面在UserBean中定义的约束规则将应用于那里。或者您可以使用类似的定义来为旧式的JSF验证器
<h:inputText value="#{personBean.name}"> <f:validateLength minimum="3"/> <rich:validator/> </h:inputText>
Length验证器的客户端实现将被注册,以便在客户端调用。
注意:您仍然可以使用JSF验证器标签,但真正优先考虑的是迁移到Bean Validation。如您所看到的示例,您仍然在视图和模型级别使用基于注解的约束重复验证,并使用单独的标签定义相同的视图验证器。
<rich:validator>是一种行为,它根据注册的服务器端验证器触发所有客户端验证器方法。作为一种行为,它可以定义在父组件的任何事件上。在之前的示例中使用了默认的事件change。让我们修改示例以使用keyup事件
<h:inputText value="#{userBean.name}"> <rich:validator event="keyup"/> </h:inputText>
Ajax回退
如果您注册了一些验证器,但它们没有可用的客户端实现,将使用Ajax回退。这意味着<rich:validator>将调用所有可用的客户端验证器。如果所有这些验证器都返回有效,RichFaces将执行Ajax请求,调用任何服务器端验证器。
注意:目前,如果客户端验证器不可用,始终使用Ajax回退。未来,我们计划设计一种方法来调用仅有的客户端验证器,而不为其他验证器发送Ajax请求RF-10142。在某些情况下可能很有用,例如当验证器使用某些复杂的远程服务调用或执行数据库调用时,不需要额外的服务器请求。
客户端验证器的消息
最后一个问题是,用户如何通过客户端验证结果进行通知?实际上,这相当简单。客户端验证器的消息将使用与用于普通服务器端验证消息相同的rich:message(s)组件来显示。
因此,让我们回顾一下完整的示例,即编辑用户信息表单
<h:form> <rich:panel header="User information"> <h:panelGrid columns="3"> <h:outputText value="Name:" /> <h:inputText value="#{validationBean.name}" id="name"> <rich:validator /> </h:inputText> <rich:message for="name" /> <h:outputText value="Email" /> <h:inputText value="#{validationBean.email}" id="email"> <rich:validator /> </h:inputText> <rich:message for="email" /> <h:outputText value="Age" /> <h:inputText value="#{validationBean.age}" id="age"> <rich:validator /> </h:inputText> <rich:message for="age" /> <h:outputText value="I agree the terms" /> <h:selectBooleanCheckbox value="#{validationBean.agree}" id="agree"> <rich:validator/> </h:selectBooleanCheckbox> <rich:message for="agree" /> </h:panelGrid> </rich:panel> </h:form>
在将任何验证器注册到h:inputText组件的情况下失败时,下面的消息将由CSV JavaScript根据信息标签更新。以下是来自richfaces-showcase应用程序的屏幕截图
所有输入的消息都未调用任何服务器端验证就出现了。脚本验证在您更改字段并将焦点移出组件后执行。在这种情况下,只发送了一个Ajax请求 - 在点击复选框后(AssertTrue验证器的客户端实现目前不可用,因此您可以看到Ajax回退的操作)。不是很容易吗?
M6功能
在RichFaces 4里程碑6中,所有与注册验证器查找、验证器脚本输出、消息和行为渲染相关的服务器端功能都已完成。至于客户端功能,所有消息、JSF验证器和大多数JSR-303验证器都是完整的。我们还有一些验证器仍然缺失(例如,AssertTrue/False、Past),但它们将在最近的时间内添加。请参阅在M6之前添加的CSV示例的开发者richfaces-showcase演示。
注意:如前所述,缺失的验证器将使用Ajax回退来调用。
现在就开始使用
尽管报告了一些小问题,并且还有一些验证器仍然缺失,但立即开始使用CSV是值得的。您在未来将无需做任何事情,以便新验证器在实现后开始工作。当您更新到下一个版本时,它们将自动由行为脚本渲染器添加,并在客户端开始工作。此外,您可以在最终版本之前帮助我们了解任何问题或担忧。
验证的未来计划
- 添加默认的验证级别支持。这意味着我们将提供一个选项,可以在某些级别自动启用 <rich:validator>,例如表单或视图。
- 支持 Action 组件。这意味着您可以将 <rich:validator> 添加到“保存”表单按钮中,并在提交前调用表单中所有输入的验证器。
- 创建自定义验证器的完整说明。基本机制已就绪,我们只需检查其工作方式并编写文档。