用
Validator
检查你的表单
作者:
James Holmes
用
Validator
(验证器)提供的丰富的内置验证方法简化
Struts
的开发过程。
Struts
框架的一个主要好处是它提供了对接收到的表单数据进行验证的内置界面。如果有任何验证失败,则应用程序都会重新显示
HTML
表单,这样就可以改正无效的数据了。如果验证成功,则处理过程会继续进行。
Struts
框架的简单验证界面会减少与处理数据验证有关的令人头疼的事情,这样你就可以把精力集中到验证代码上,而不是放到捕获数据、重新显示不完整或无效数据的技巧上。
但是,
Struts
内置的验证界面也有缺点。例如,在整个应用程序中验证代码常常会大量重复,因为许多域需要相同的验证逻辑。对一些相似字段的验证逻辑进行任何修改都要求在几个地方修改代码,还要重新编译受影响的代码。为了解决这个问题并增强
Struts
验证界面的功能,作为
Struts
的第三方附加件创建了
Validator
框架。后来,
Validator
被集成到核心
Struts
代码库中,并从
Struts
中分离出来,现在它是一个独立的
Jakarta Commons
项目。虽然
Validator
是一个独立的框架,但它仍能与其他程序封装在一起后提供,并与
Struts
无缝集成。
Validator
概述
没有
Validator
,你就不得不编写验证表单数据所需的全部代码,并把它放入
Form Bean
对象的
validate( )
方法中。对于想在其上进行数据验证的每个
Form Bean
域来说,都需要编写逻辑代码来实现验证。此外,你还必须编写代码来存储验证失败时的出错消息。
有了
Validator
,你就不必在
Form Bean
中编写用于验证或存储错误消息的任何代码。相反,
Form Bean
提供了
Validator
的一个
ActionForm
子类,它提供验证或存储错误消息的功能。
可把
Validator
框架作为一个可用于
Form Bean
验证的可插入的验证例行程序系统来进行安装。每个验证例行程序都只是一个
Java
方法,负责执行特定类型的验证任务,验证可能通过,也可能失败。
默认情况下,
Validator
与几个有用的验证例行程序封装在一起来提供,这些例行程序能满足大多数情况下的验证要求。但是,如果
Validator
框架没有提供你需要的验证例行程序,那么你可以自己创建定制的验证例行程序,并将它插入到该框架中。此外,
Validator
还支持服务器端和客户端(
JavaScript
)的验证,而
Form Bean
只提供服务器端验证界面。
Validator
使用两个
XML
配置文件来分别确定安装哪个验证例行程序和如何将它们应用于给定的应用程序。第一个配置文件
validator-rules.xml
说明应该被插入到框架中的验证例行程序,并提供每个验证的逻辑的名称。
validator-rules.xml
文件还定义了每个验证例行程序的客户端
JavaScript
代码。可以配置
Validator
让它把这个
JavaScript
代码发送到浏览器上,这样验证就可以在客户端和服务器端进行了。
第二个配置文件
validation.xml
确定哪个验证例行程序应用到哪个
Form Bean
。文件中的定义使用
struts-config.xml
文件给出的
Form Bean
的逻辑名称以及
validator-rules.xml
文件给出的验证例行程序的逻辑名称,以便把二者关联起来。
使用
Validator
框架包括启用
Validator
插件、配置
Validator
的两个配置文件,以及创建提供
Validator
的
ActionForm
子类的
Form Beans
。下面详细解释如何配置和使用
Validator
。
启用
Validator
插件
虽然
Validator
框架是与
Struts
封装在一起提供的,但在默认状况下
Validator
并不被启用。为了启用
Validator
,要向你的应用程序的
struts-config.xml
文件中添加下面的插件定义。
<!-- Validator Configuration -->
<plug-in className="org.apache.struts
.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/
validator-rules.xml, /WEB-INF/
validation.xml"/>
</plug-in>
该定义告诉
Struts
为你的应用程序加载并初始化
Validator
插件。在初始化时,该插件装入由路径名属性指定的、用逗号分隔的
Validator
配置文件清单。每个配置文件的路径应该用与
Web
应用程序的相关的路径来指定,如前面的例子所示。
请注意,你的应用程序的
struts-config.xml
文件必须与
Struts Configuration Document Type Definition
(
Struts
配置文档类型定义,
DTD
)一致,后者规定文件中元素出现的顺序。所以,你必须把
Validator
插件定义放到该文件的适当位置。确保文件中元素适当排列的最简便方法就是使用诸如
Struts Console
的工具,它自动格式化你的配置文件,以便与
DTD
保持一致。
配置
validator-rules.xml
Validator
框架可以设置为可插入系统,其验证例行程序仅仅是插入到该系统中执行具体验证的
Java
方法。
validator-rules.xml
文件说明性地插入
Validator
用于执行验证的验证例行程序中。
Struts
示例应用程序带有这个文件的预配置拷贝。在大多数情况下,你不必修改这个预配置拷贝,除非你要向该框架中添加自己定制的验证。
清单
1
是一个示例
validator-rules.xml
文件,说明如何将验证例行程序插入到
Validator
中。
validator-rules.xml
文件中的每个验证例行程序都有自己的定义,它用
validator
标记声明,利用
name
属性为该验证例行程序指定逻辑名,并指定该例行程序的类和方法。该例行程序的逻辑名称供该文件中的其他例行程序以及
validation.xml
文件中的验证定义用于引用该例行程序。
请注意,
validator
标记放在
javascript
的标记中,
javascript
标记用于定义客户端
JavaScript
代码,以便在客户端执行与服务器端相同的验证。
提供的验证程序
默认情况下,
Validator
中包括几个基本验证例行程序,你可以用它们来处理大多数验证问题。这些例行程序具有逻辑名称,如
required
(用于输入要求的值)、
CreditCard
(用于输入信用卡号码值)、
email
(用于输入电子邮件地址值),等等。
创建
Form Bean
为了使用
Validator
,你的应用程序的
Form Bean
必须归到
Validator
的
ActionForm
的某一子类,而不是
ActionForm
本身。
Validator
的
ActionForm
子类提供了
ActionForm
的
validate( )
方法(它嵌入到
Validator
框架中)的实施过程。你不必从头编写验证代码并把它投入
validate( )
方法中,相反,可以完全忽略该方法,因为
Validator
为你提供了验证代码。
与
Struts
提供的核心功能相类似,
Validator
提供给你两种可供选择的方法来创建
Form Bean
。
你可以选择的第一种方法就是像下面这样创建一个特定的
Form Bean
对象:
package com.jamesholmes.minihr;
import org.apache.struts.validator
.ValidatorForm;
public class LogonForm extends ValidatorForm {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String
username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String
password) {
this.password = password;
}
}
这个类与你不是用
Validator
所创建的类相似,但它提供
ValidatorForm
而不是
ActionForm
。这个类也不提供
ActionForm
的空
reset( )
和
validate( )
方法的实施过程,因为
ValidatorForm
提供了相应过程。
在
struts-config.xml
文件中配置这个特定
Form Bean
的方法与配置正则
Form Bean
的方法相同:
<form-beans>
<form-bean name="logonForm"
type="com.jamesholmes
.minihr.LogonForm"/>
</form-beans>
用表单标记的
name
属性给特定
Form Bean
指定的逻辑名是在定义
validation.xml
文件中的验证时所使用的名称,如下所示:
<!DOCTYPE form-validation
PUBLIC "-//Apache Software Foundation//
DTD Commons Validator Rules
Configuration 1.0//EN"
"http://jakarta.apache.org/
commons/dtds/validator_1_0.dtd">
<form-validation>
<formset>
<form name="logonForm">
<field property="username"
depends="required">
<arg0 key="prompt.username"/>
</field>
</form>
</formset>
</form-validation>
Validator
使用该表单标记的
name
属性的值将验证定义与要应用这些定义的
Form Bean
的名称相匹配。
创建
Form Bean
时可以选择的第二种方法是在
struts-config.xml
文件中定义一个动态
Form Bean
,如下所示:
<form-beans>
<form-bean name="logonForm"
type="org.apache
.struts.validator.DynaValidatorForm">
<form-property name="username"
type="java.lang.String"/>
<form-property name="password"
type="java.lang.String"/>
</form-bean>
</form-beans>
动态
Form Bean
不要求创建特定的
Form Bean
对象;相反,要定义
Form Bean
应该具有的属性和类型,而
Struts
为你动态创建
Form Bean
。
Validator
允许你使用这个概念,就像在核心
Struts
中使用这个概念一样。与使用
Validator
的惟一区别就是要指定
Form Bean
是
org.apache.struts.validator.DynaValidatorForm
类型,而不是
org.apache.struts.action.DynaActionForm
类型。
分配给动态
Form Bean
的逻辑名是在定义
validation.xml
文件中的验证时使用的名称。
Validator
使用与之相匹配的名称将这些验证与
Form Bean
联系在一起。
除了创建
Form Bean
的这两种标准方法之外,
Validator
还提供了一个高级特性,用于将多个验证定义与一个
Form Bean
定义联系起来。当你使用基于
validatorForm
或基于
DynaValidatorForm
的
Form Bean
时,
Validator
使用
struts-config.xml
文件中的
Form Bean
的逻辑名称,将
Form Bean
映射到
validation.xml
文件中的验证定义。这种机制在大多数情况下非常有用,但在某些时候,
Form Bean
要在多个操作中共享。
一个操作可能使用
Form Bean
的所有域(
fields
),而另一个操作可能只使用这些域的一个子集。因为验证定义被连接到
Form Bean
,所以只使用域的一个子集的操作就无法绕过对未使用域的验证。当验证
Form Bean
时,就会对未使用的域生成错误消息,因为
Validator
无从知道不去验证未使用的域,它只是简单地把它们看作缺失或无效。
为了解决这个问题,
Validator
提供了两个附加的
ActionForm
子类,它使你能够将验证与操作相关联,而不是与
Form Bean
相关联。这样你就可以根据哪个操作正在使用
Form Bean
来指定把哪些验证用于该
Form Bean
了。对于特定的
Form Bean
,你要像下面这样声明
org.apache.struts.validator.ValidatorActionForm
子类:
public class AddressForm extends ValidatorActionForm {
...
}
对于动态
Form Bean
,在
struts-config.xml
文件中为
Form Bean
定义指定
org.apache.struts.validator.DynaValidatorActionForm
的类型,如下所示:
<form-bean name="addressForm"
type="org.apache.struts
.validator.DynaValidatorActionForm">
...
</form-bean>
在
validation.xml
文件中,把一组验证映射到一个操作路径,而不是映射到
Form Bean
名,因为如果你定义了
Create Address
和
Edit Address
两个操作(它们使用同一个
Form Bean
),那么每个操作都会有一个惟一的操作名,如下所示:
<action-mappings>
<action path="/createAddress"
type="com.jamesholmes
.minihr.CreateAddressAction"
name="addressForm"/>
<action path="/editAddress"
type="com.jamesholmes
.minihr.EditAddressAction"
name="addressForm"/>
</action-mappings>
下面的
validation.xml
文件片断显示了两组验证,它们用于同一个
Form Bean
,但却有不同的操作路径:
<formset>
<form name="/createAddress">
<field property="city"
depends="required">
<arg0 key="prompt.city"/>
</field>
</form>
<form name="/editAddress">
<field property="state"
depends="required">
<arg0 key="prompt.state"/>
</field>
</form>
</formset>
因为
Form Bean
要么属于
ValidatorActionForm
子类,要么属于
DynaValidatorActionForm
子类,所以
Validator
知道用一个操作路径代替
Form Bean
的逻辑名称来找出用于
Form Bean
的验证。
配置
validation.xml
文件
validation.xml
文件用于声明将应用到
Form Beans
的一组验证。要验证的每个
Form Bean
在这个文件中都有自己的定义。在这个定义中,指定要应用到该
Form Bean
的各域的验证。下面是一个
validation.xml
文件的例子,说明如何定义验证:
<!DOCTYPE form-validation
PUBLIC "-//Apache Software Foundation//
DTD Commons Validator Rules
Configuration 1.0//EN"
"http://jakarta.apache.org/
commons/dtds/validator_1_0.dtd">
<form-validation>
<formset>
<form name="logonForm">
<field property="username"
depends="required">
<arg0 key="prompt.username"/>
</field>
<field property="password"
depends="required">
<arg0 key="prompt.password"/>
</field>
</form>
</formset>
</form-validation>
validation.xml
文件的第一个元素是
form-validation
。这个元素是该文件的主元素,而且只定义一次。在
form-validation
元素内定义
form-set
元素,它包括多个表单元素。一般来说,在文件中只定义一个
form-set
元素,但是如果要将验证国际化,那就要在每个地方单独使用一个
form-set
元素。
每个表单元素使用
name
属性将名称与其所包含的域验证集关联起来。
Validator
使用这个逻辑名称将这些验证映射到在
struts-config.xml
文件中定义的一个
Form Bean
。根据要验证的
Form Bean
的类型,
Validator
力求将该名称与
Form Bean
的逻辑名称或操作路径相匹配。在表单元素内,
field
元素定义要应用到
Form Bean
的特定域的验证。
field
元素的
property
属性对应于特定
Form Bean
中的域名。
depends
属性利用
validator-rules.xml
文件指定验证例行程序的逻辑名称,这些例行程序将应用到域验证中。
配置
ApplicationResources.properties
Validator
使用
Struts
的资源绑定(
Resource Bundle
)机制将错误消息具体化。不用在框架中对错误消息进行硬编码,
Validator
使你能在
ApplicationResources.properties
文件中为一个消息指定一个键值,如果验证失败则将返回该键值。
validator-rules.xml
文件中的每个验证例行程序都用
validator
标记的
msg
属性指定错误消息的键值,如下所示:
<validator name="required"
classname="org.apache
.struts.validator.FieldChecks"
method="validateRequired"
methodParams="java.lang
.Object, org.apache.commons.validator
.ValidatorAction, org.apache.commons
.validator.Field, org.apache.struts
.action.ActionErrors, javax.servlet
.http.HttpServletRequest"
msg="errors.required">
如果在验证例行程序运行时验证失败,则返回与
msg
属性指定的键值对应的消息。
下面的片段显示来自
ApplicationResources.properties
文件的验证出错时的默认消息集,它们由
Struts
示例应用程序提供。每个消息的键值对应于每个由
validator-rules.xml
文件中的验证例行程序所指定的消息,它们由
Struts
示例应用程序提供。
# Error messages for Validator framework validations
errors.required={0} is required.
errors.minlength={0} cannot be less than {1} characters.
errors.maxlength={0} cannot be greater than {2} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.0. errors.float={0} must be a float.
errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
请注意,每条消息都有占位符,形式为
{0}
、
{1}
或
{2}
。在运行期间,占位符被另一个值代替,如所验证的域的名称。这一特性特别有用,它使你能够创建可被几个不同的域重复使用的通用验证错误消息。
例如,下面给出
required
验证的错误消息
errors.required
:
errors.required={0} is required.
当你使用
validation.xml
文件中的该
required
验证时,必须定义用于替换该错误消息中的
{0}
的值,如下所示:
<form name="auctionForm">
<field property="bid" depends="required">
<arg0 key="prompt.bid"/>
</field>
</form>
错误消息最多可以有
4
个占位符:
{0}
和
{3}
。这些占位符分别称为
arg0
到
arg3
,你可以通过使用
arg0~arg3
标记来指定它们。在上面的例子中,
arg0
标记指定了用于替换
{0}
占位符的值。该标记的
key
属性指定来自
ApplicationResources.properties
文件的一个消息键值,它的值用于替换占位符,如下所示:
prompt.bid=Auction Bid
使用消息键值代替占位符的值,这一方法使你不必在
validation.xml
文件中对替换值反复硬编码。但是,如果你不想使用
Resource Bundle
的键值
/
值机制来指定占位符的值,则可以使用
arg0
标记的如下语法显式地指定占位符的值:
<arg0 key="Auction Bid" resource="false"/>
在这个例子中,
resource
属性的值设为
false
,以便通知
Validator
要把该
key
属性指定的值作为占位符的值,而不要作为
ApplicationResources.properties
文件中消息的一个键值。
启用客户端验证
Validator
除了提供了简化服务器端表单数据验证过程的框架外,它还提供了执行客户端验证时易于使用的方法。在
validator-rules.xml
文件中定义的每一个验证例行程序都可以随意指定
JavaScript
代码,这些代码可以在浏览器(客户端上的)中运行,从而执行与服务器端进行的验证相同的验证过程。在客户端进行验证时,除非所有表单都通过验证,否则这些表单不允许被提交。
为了启用客户端验证,必须在每个需要验证的
JSP
中放上
Struts HTML Tag Library
(标记库)的
javascript
标记,如下所示:
<html:javascript formName="logonForm"/>
javascript
标记要求使用
formName
属性来为想要对其执行验证的表单指定
validation.xml
文件中给出的表单定义名,如下所示:
<form name="logonForm">
<field property="username"
depends="required">
<arg0 key="prompt.username"/>
</field>
<field property="password"
depends="required">
<arg0 key="prompt.password"/>
</field>
</form>
为表单定义指定的服务器端的所有验证都将在客户端运行。由于客户端验证用
JavaScript
执行,所以可以有多种方法不去执行它。要确保验证过程总是能运行,不论你是否选择启用了客户端验证,
Validator
都在服务器端执行这些验证。
结论
Validator
框架针对表单数据的验证提供了可配置的系统,从而为核心
Struts
框架添加了很多有价值的功能。通过把
Validator
框架用于你的应用程序,你可以节约时间并简化
Struts
应用程序的开发过程。