struts2能够对前台提交的表单数据进行输入有效性校验,通常有两种方式:
1、在Action类中通过validatexx方法验证,这种方式很简单,在此不再赘述;
2、通过编写xx-validation.xml文件执行表单验证,当用户提交表单请求后,struts会优先执行xml文件,如果校验不通过是不会让请求访问指定action的。
本文介绍一下struts2通过xml文件进行校验的方法并说明怎么样扩展自定义的验证。
一、struts2验证框架的包位置
部署struts2项目有一个必备jar包:xwork-core-*.jar,在这个包中有这样一个package"com.opensymphony.xwork2.validator.validators",所有官方验证类就放在这下面的,在这个包下面有一个"default.xml"文件,这就是验证框架的核心文件,里面配置了所有的验证类数据。
验证类的格式为:<validator name="别名" class="验证类"/>,在配置的时候只需要使用别名就能执行指定验证了。
在这介绍struts2的几个常用的验证类:
required:字段不能为空
requiredstring:字符串不能为空
int:int类型(可指定范围)
long:long类型(可指定范围)
short:short类型(可指定范围)
double:double类型(可指定范围)
date:时间格式(可指定范围)
expression:ognl表达式判断
fieldexpression:ognl表达式判断
email:邮箱判断
url:url路径判断
visitor:把同一个验证程序配置文件用于多个动作(对一个Bean写验证文件,每个使用的Action只要引用)
conversion:格式转换
stringlength:字符串长度
regex:正则表达式判断
这里有个地址详细介绍了这几种验证的使用方法,大家可以参考下:http://code.google.com/p/j2eewiki/wiki/Struts2Validator
以上验证乍看还是非常全面的,但是很多验证功能还不够强大(比如stringlength是把任何文字都当做1的长度,而中文像UTF-8是3个字节的长度,这样验证效果就不准确了),所以很多时候是需要进行自定义验证的,这个随后再说。
二、使用xml配置验证
①copy上面提到的"default.xml"文件到Action同级目录下,修改文件名为"action名-validation.xml"。假设有这样一个Action:com.struts.action.UserAction.java,那么你需要将xml文件放到com.struts.action包下面,并且改名为"UserAction-validation.xml"。
②删除标签<validators>里所有的内容,并且更改xml上面的dtd版本为1.0.2.dtd,这里我也不知道为什么1.0.0跑不起,反正改了就能执行了。
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
③编写验证文件,field标签表示被验证的字段项,field-validator标签表示使用什么验证约束,short-circuit表示如果有多个验证约束时只要有一个不通过则后面就不执行验证了,message表示验证不通过时返回的错误消息。
<field name="user.name"> <field-validator type="requiredstring" short-circuit="true"> <message>用户名不能为空</message> </field-validator> </field>
按照上面三步,一个基本的验证就出来了,大家可以去试试,只要提交的表单访问UserAction都会先通过xml的验证。假如你只想验证UserAction中的userAdd方法(该方法的请求路径为userAdd.action),则只需要将xml文件改名为"UserAction-userAdd-validattion.xml"即可。[特别注意:这个xml名称中的userAdd并非指Action中的方法名,而是指配置文件中的请求名,就是那个<action name="请求名">]
三、扩展struts2验证类
其实自定义验证类很简单,你只需要仿照struts2的任何一个验证类就能做出来,前面提到不能验证utf-8格式的字符长度,我们在这就做一个获取utf-8长度的自定义框架。
①创建验证框架扩展类,这里必须继承 FieldValidatorSupport 类,重写validate方法,具体验证代码就在validate方法中写,这里的get、set就是在xml中出现的属性参数。这段代码还不够好,其实可以把encoding也作为属性的,这样传入任何编码格式都能获取该编码对应的字符长度。
public class CheckStringLength extends FieldValidatorSupport { private boolean trim; // 是否去首位空格 private int minLength; //最大长度 private int maxLength; //最小长度 private static final String ENCODING = "UTF-8"; //编码格式(默认utf-8) /* * 构造方法初始化默认数据 */ public CheckStringLength() { this.trim = true; this.minLength = -1; this.maxLength = -1; } public boolean isTrim() { return trim; } public void setTrim(boolean trim) { this.trim = trim; } public int getMinLength() { return minLength; } public void setMinLength(int minLength) { this.minLength = minLength; } public int getMaxLength() { return maxLength; } public void setMaxLength(int maxLength) { this.maxLength = maxLength; } @Override public void validate(Object arg0) throws ValidationException { String fieldName = this.getFieldName(); String val = (String) this.getFieldValue(fieldName, arg0); //如果值为空则直接不通过 if (val == null || val.length() <= 0) { return; } if (trim) { val = val.trim(); ////如果值为空则直接不通过 if (val == null || val.length() <= 0) { return; } } int length = 0; try { //根据编码格式获得字符长度 length = val.getBytes(ENCODING).length; } catch (UnsupportedEncodingException e) { length = val.getBytes().length; } /* *判断字符长度范围 */ if (minLength > -1 && length < minLength) { this.addFieldError(fieldName, arg0); } if (maxLength > -1 && length > maxLength) { this.addFieldError(fieldName, arg0); } } }
②新建validators.xml文件,将"default.xml"的配置信息和自定义验证类的配置信息放到文件中,最后把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="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="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/> <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/> <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"/> <validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/> <!-- 自定义验证规则 --> <validator name="stringlengthencoding" class="com.bless.struts2.validate.CheckStringLength"/> </validators>
③按照前面所说的编写表单验证规则,注意这里的param就是上面CheckStringLength类中的属性,但是属性是根据get、set方法来的 (因为struts2做了一个很蛋痛的事:他的验证类中有这样一个属性"doTrim",但是该属性对应的get、set方法是getTrim、setTrim,配置文件里必须这样写<param name="trim">false</param>,记住是根据set方法配置param)。
<!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="user.name"> <field-validator type="requiredstring" short-circuit="true"> <message>用户名不能为空</message> </field-validator> <field-validator type="stringlengthencoding" short-circuit="true"> <param name="maxLength">10</param> <param name="minLength">6</param> <message>用户名必须是6到10位字符!</message> </field-validator> </field> </validators>
基本上一个简单的自定义验证就完成了,大家可以手动试试,这个东西确实很简单。
最后附上扩展的几个验证类,希望对大家有所帮助 :
<!-- 根据编码格式获取字符串长度,并且可以校验长度范围 --> <validator name="stringlengthencoding" class="com.bless.struts2.validate.CheckStringLength"/> <!-- 检查常用的格式,目前能验证:邮箱、手机、固定电话和身份证号 --> <validator name="checkformat" class="com.bless.struts2.validate.CheckFormat"/> <!-- 检查是否是半角字符 --> <validator name="checkhalfwidthdigit" class="com.bless.struts2.validate.CheckHalfWidthDigit"></validator> <!-- 检查字符串格式,这里可以中文、字母、数字和符号任何组合配置 --> <validator name="checkspecialchar" class="com.bless.struts2.validate.CheckSpecialChar"></validator> <!-- 检查时间 --> <validator name="checkdate" class="com.bless.struts2.validate.CheckDate"/> <!-- 检查小数值,可以验证小数点精确范围 --> <validator name="checkdoublerange" class="com.bless.struts2.validate.CheckDoubleAccuracy"/>
最后感谢同事jwt童鞋做的扩展框架。