8.1 验证程序概述
分成两种:
Ø 字段验证程序:与表单里的某个字段相关联,其验证行为发生在把一个值赋给一个动作属性之前。Struts内建验证一般都为字段验证
Ø 普通验证程序:不与某个特定的字段相关联,用来测试某种特定的条件是否得到满足。
Validation拦截器负责加载和执行已注册的验证程序,是defaultStack拦截器栈中的一员
使用一个验证程序需要如下三个步骤
1) 确定哪些动作的输入需要验证
2) 编写验证程序的配置文件,其名字为actionClass-validation.xml 或者actionClass-alias-validation.xml,如:对userAction进行验证,其名字为userAction-validation.xml,如果userAction里有两个动作create 和edit,两者的验证程序不一样,则要为两种动作分别配置验证程序,名字为userAction_create-validation.xml,
userAction_edit-validation.xml
3) 确定在验证失败时应将用户定位到什么地方,一般在struts.xml里面配置,如<result name=”input”>error.jsp</result>
注意:如果要使用一个自定义的验证程序,千万不要忘记对其注册。
8.2 验证程序的配置
配置文件是按照XWork validator DTD规则编写出来的XML文档
一个典型的配置文件
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <validators> <field name=" "> <field-validator type=""></field-validator> <field-validator type=""></field-validator> </field> <validator type=""> .... </validator> </validators>
其中,field里的name对应表单的字段,里面嵌入的field-validator为该字段的验证程序,type标识该验证程序,可以为一个表单字段规定多个验证程序。validator元素标识一个普通验证程序。
field-validator有一个short-circuit的属性,如果该属性为true,则表明如果当前的验证程序失败了,将不执行同一字段的下一个验证程序。
field-validator和validator元素内可以嵌入param元素向验证程序传入参数,可以嵌入message属性定义一条验证程序出错时的提示信息。如下:可以有多个param 元素,但只能有一个message
<validator type="expression"> <param name="minLength">6</param> <param name="maxLength">14</param> <message>User name must between 6 and 14 charactes long</message> </validator>
8.3 struts 内建验证程序
8.3.1 required验证程序
用来验证某给定字段的值不为null,注意空字符串不等于null.
如UserAction.java有两个属性name,password
import com.opensymphony.xwork2.ActionSupport; public class UserAction extends ActionSupport{ private String name; private String password; //getter and setter }
相应的JSP的表单里两个字段分别对应name和password,验证输入的name和password不为空,配置文件如下:
UserAction-validation.xml
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <validators> <field name="name"> <field-validator type="required"> <message>Please enter a name</message> </field-validator> </field> <field name="password"> <field-validator type="required"> <message>Please enter a password</message> </field-validator> </field> </validators>
8.3.2 requirestring内建程序
验证输入字段的值不是null,也不为空(empty),有一个trim参数,默认true,意思是在验证前会先剔除前导和后缀的空白字符。如果trim的值为true,只包含空格的字段将不能通过验证。
配置文件如下:
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <validators> <field name="name"> <field-validator type="requirestring"> <param name="trim">true</param> <message>Please enter a name</message> </field-validator> </field> <field name="password"> <field-validator type="requirestring"> <param name="trim">false</param> <message>Please enter a password</message> </field-validator> </field> </validators>
如上,如果输入password为空格,会通过验证。
8.3.3 stringlength验证
用来验证一个非空字段值是不是有足够的长度,有三个参数
Ø minLength: 相关字段所应达到的最小长度,如果没有给出该参数,没有最小长度限制
Ø maxLength: 相关字段所应达到的最大长度,如果没有给出该参数,没有最小长度限制
Ø trim: 是否剔除前导和后缀的空格字符
配置文件如下:
<validators> <field name="name"> <field-validator type="stringlength"> <param name="minLength">6</param> <param name="maxLength">14</param> <param name="trim">true</param> <message>Please enter a name between 6 and 14 long</message> </field-validator> </field> </validators>
8.3.4 int 验证程序
用来验证给定字段的值是否能转换为一个int类型的值,如果还有min ,max属性的话,验证该值是不是在这个范围内
如action里有一个year属性,输入的year必须在1990-2009之间,配置文件如下
<validators> <field name="year"> <field-validator type="int"> <param name="min">1990</param> <param name="max">2009</param> <message>the year must between 1990 and 2009</message> </field-validator> </field> </validators>
8.3.5 date验证程序
验证给定字段的值落在一个给定的范围内,有两个参数,min,max
如action里有一个Date birthDate, 验证birthDate在1980.1.1-2011.12.31之间,如下配置文件
</validators> <field name="birthDate"> <field-validator type="date"> <param name="min">1/1/1980</param> <param name="max">31/12/2011</param> <message>the birthDate must between 1/1/1980 and 31/12/2011 </message> </field-validator> </field> </validators>
8.3.6 email验证
验证给定字段值是否为合法的email
<field name="email"> <field-validator type="email"> <message>Invalid email</message> </field-validator> </field>
8.3.7 url验证
验证给定字段值是否为合法的url
<field name="url"> <field-validator type="url"> <message>Invalid url</message> </field-validator> </field>
8.3.8 regex验证程序
用来验证一个给定字段的值是否与一个给定的正则表达式模式相匹配,参数如下:
Ø expression:必须, String类型,用来进行匹配的正则表达式模式
Ø caseSensitive: boolean类型,是否区分字母的大小写情况,默认值为true
Ø trim: boolean类型,是否剔除前导和尾缀的空白字符,默认值为true
8.3.9 expression和fieldexpression验证程序
参数expression:
必须有,有来验证的OGNL表达式
两者区别:
Ø 后者是一个字段验证,前者不是
Ø 前者验证失败生成一个actiroerror,后者验证失败抛出一个字段错误
l expression验证程序示例
ExpressionTestAction-validation.xml
<validators> <validator type="expression"> <param name="expression"> max>min </param> <message> max must be greater than min </message> </validator> </validators>
其中,ExpressionTestAction里面有max, min属性
jsp页面
<div id="global"> <s:actionerror /> <s:form action="expression"> <s:textfield name="min" label="minimum" /> <s:textfield name="max" label="maximum" /> <s:submit /> </s:form> </div>
注意红色部分<s:actionerror />即为触发的动作错误
l fieldexpression验证程序
fieldExpressionTestAction-validation.xml
<validators> <field name="max"> <field-validator type="fieldexpression"> <param name="expression"> max>min </param> <message> max must be greater than min </message> </ field-validator > </ field> </validators>
为字段验证
8.3.10 conversion验证程序
用来检查某个动作属性进行的类型转换是否会导致一个转换错误,默认的出错信息为“Invalid field value for field “fieldname””,如果使用了conversion验证程序,可以再增加错误信息。如下
<validators> <field name="age"> <field-validator type="conversion"> <message>An age must be an integer</message> </field-validator> </field> </validators>
8.3.11 visitor验证
两个用途:
Ø 将反复用到的验证程序提取出来保存为一个文件
Ø 可以引用上下文
引用上下文的命名规则:
如果有多个使用了Address的动作,但其中有一个需要使用的验证规则与Address-validation.xml文件所给出的不一样,可以只为那个动作创建一个新的验证配置文件,命名为Address-context-validation.xml,其中context为需要为Address类另行定义验证规则的动作别名,如Address-addCustomer-validation.xml;
如果上下文的名字与动作别名不一样,设AddManager动作也需要用到Address-addCustomer-validation.xml里面的验证规则,则可以通过field元素来告诉visitor验证程序需要另一种上下文,如
<field name="address"> <field-validator type="visitor"> <param name=”context”>specific</param> <message>Address:</message> </field-validator> </field>
表明验证Address时,应该使用Address-specific-validation.xml文件。
直接看例子
customer类
package app07a; import com.opensymphony.xwork2.ActionSupport; public class Customer extends ActionSupport{ private String firstname; private String lastname; private Address address; //getter and setter }
Address类
package app07a; public class Address { private String streetName; private String city; private String zipCode; //getter and setter }
Ø 普通验证
Customer-validation.xml
<validators> <field name="firstname"> <field-validator type="requirestring"> <message>firstname must not be empty</message> </field-validator> </field> <field name="lastname"> <field-validator type="requirestring"> <message>lastname must not be empty</message> </field-validator> </field> <field name="address.streetName"> <field-validator type="requirestring"> <message>streetName must not be empty</message> </field-validator> </field> <field name="address.city"> <field-validator type="requirestring"> <message>city must not be empty</message> </field-validator> </field> <field name="address.zipCode"> <field-validator type="requirestring"> <message>zipCode must not be empty</message> </field-validator> </field> </validators>
Ø visitor验证
Address-validation.xml
<validators> <field name="streetName"> <field-validator type="requirestring"> <message>streetName must not be empty</message> </field-validator> </field> <field name="city"> <field-validator type="requirestring"> <message>city must not be empty</message> </field-validator> </field> <field name="zipCode"> <field-validator type="requirestring"> <message>zipCode must not be empty</message> </field-validator> </field> </validators>
Customer-validation.xml
<validators> <field name="firstname"> <field-validator type="requirestring"> <message>firstname must not be empty</message> </field-validator> </field> <field name="lastname"> <field-validator type="requirestring"> <message>lastname must not be empty</message> </field-validator> </field> <field name="address"> <field-validator type="visitor"> <message>Address:</message> </field-validator> </field> </validators>
注意红色部分
Ø 在不同的上下文里使用visitor验证
Address-specific-validation.xml
<validators> <field name="zipCode"> <field-validator type="regex"> <param name="expression"><![CDATA[\d\d\d\d\d]]></param> <message>Invalid zip code or invalid format</message> </field-validator> </field> </validators>
Employee-validation.xml
<validators> <field name="firstname"> <field-validator type="requirestring"> <message>firstname must not be empty</message> </field-validator> </field> <field name="lastname"> <field-validator type="requirestring"> <message>lastname must not be empty</message> </field-validator> </field> <field name="address"> <field-validator type="visitor"> <param name=”context”>specific</param> <message>Address:</message> </field-validator> </field> </validators>
注意红色部分
8.4编写自定义的验证程序
自定义的验证程序需实现validator接口,它是com.opensymphony.xwork2.validator包的一部分。接口如下:
package com.opensymphony.xwork2.validator; public interface Validator { void setDefaultMessage(String message); String getDefaultMessage(); String getMessage(Object object); void setMessageKey(String key); void getMessageKey(); void setValidatorType(String type); String getValidatorType(); void setValidatorContext(ValidatorContext validatorContext); ValidatorContext getValidatorContext(); void validate(Object object)throws ValidationException; }
Validation拦截器负责加载和执行各种验证程序。在加载了一个验证程序之后,这个拦截器将调用那个验证程序的 setValidatorContext方法,并把当前的ValidatorContext对象传递给它,这使我们可以访问当前动作。接下来,Validation拦截器将调用validate方法并把需要验证的对象传递给它。validate方法是你在编写一个自定义的验证程序时需要覆盖的方法。
对便捷类ValidatorSupport或FieldValidatorSupport进行扩展要比自行实现Validator接口容易得多。如果你想创建一个普通的验证程序(非字段验证程序),请扩展ValidatorSupport类。如果你想编写一个字段验证程序,请扩展 FieldValidatorSupport类。如果你设计的验证程序能够接受一个输入参数,你还需要为这个参数增加一个相应的属性。例如,如果你的验证 程序允许一个minValue参数,你还需要增加一个名为minValue的属性,并为它编写getter方法和setter方法。
ValidatorSupport类增加了几个方法,下面3个是便捷方法,你可以从验证程序类里调用它们。
protected java.lang.Object getFieldValue(java.lang.String name,java.lang.Object object) throws ValidationException
返回Object的name字段的值
protected void addActionError(java.lang.Object actionError)
增加一个动作错误
protected void addFieldError (java.lang.String propertyName,java.lang.Object object)
增加一个字段错误
如果编写的为一个字段验证程序,则验证失败时调用addFieleError方法,如果编写的为非字段验证程序,则验证失败时调用addActionError方法。
8.4.1注册
自定义的验证程序需要进行注册
Struts内建的验证程序已经注册过,使用之前不用再注册它们,它们在
com/opensymphony/xwork2/validator/validators/default.xml里面注册的,而该文件打包在xwork.jar文件里。
default.xml如下所示:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator Config 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd"> <!-- START SNIPPET: validators-default --> <validators> <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/> <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/> <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/> <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/> <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/> <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/> <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/> <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/> <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/> <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/> <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/> <validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/> <validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/> </validators>
8.4.2 示例
下面的例子为自定义一个验证程序,并注册使用
该例子为一个用来检查口令强度的strongpassword的验证程序:只有那些至少包含一个数字、一个小写字母和一个大写字母的口令字才会被认为是一个强口令字。此外,还接受一个minLength参数,可以通过这个参数设置一个可接受口令字的最小长度。
StrongPasswordValidator.java
package app08e; import com.opensymphony.xwork2.validator.ValidationException; import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport; public class StrongPasswordValidator extends FieldValidatorSupport{ private int minLength=-1; public int getMinLength() { return minLength; } public void setMinLength(int minLength) { this.minLength = minLength; } public void validate(Object object) throws ValidationException { String fieldName=getFieldName(); String value=(String)getFieldValue(fieldName,object); if(value==null||value.length()==0){ //use a required validator for these return; } if((minLength>-1)&&(value.length()<minLength)){ addFieldError(fieldName,object); }else if(!isPasswordStrong(value)){ addFieldError(fieldName,object); } } private static final String GROUP_1="abcdefghijklmnopqrstuvwxyz"; private static final String GROUP_2="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final String GROUP_3="0123456789"; protected boolean isPasswordStrong(String password){ boolean ok1=false; boolean ok2=false; boolean ok3=false; int length=password.length(); for(int i=0;i<length;i++){ if(ok1&&ok2&&ok3){ break; } String character=password.substring(i,i+1); if(GROUP_1.contains(character)){ ok1=true;continue; } if(GROUP_2.contains(character)){ ok2=true;continue; } if(GROUP_3.contains(character)){ ok3=true;continue; } } return (ok1&&ok2&&ok3); } }
注册,validators.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator Config 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd"> <validators> <validator name="strongpassword" class="app08e.validator.StrongPasswordValidator"/> </validators>
Users类
package app08e; import com.opensymphony.xwork2.ActionSupport; public class Customer extends ActionSupport{ private String username; private String password; //getter and setter }
同时使用内建验证,密码不为空
User-validation.xml
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <validators> <field name="username"> <field-validator type="requirestring"> <message>username must not be empty</message> </field-validator> </field> <field name="password"> <field-validator type="requirestring"> <message>password must not be empty</message> </field-validator> </field> <field name="password"> <field-validator type="strongpassword"> <param name=”minLength”>8</param> </field-validator> </field> </validators>
8.5 利用Validateable接口实现编程验证
即在action里面实现这个接口,在action里面实现validate()进行验证,如果该action继承了ActionSupport,即可直接实现 validate方法,由于ActionSupport已经实现了这个接口。