校验分为客户端校验跟服务器校验。客户端主要依靠javascript代码完成,服务器端校验通过在程序中的编程完成。客户端仅能防止正常的误操作从而减低服务器的负载,而服务器端则可以防止恶意的攻击。
编写校验规则文件
Struts2提供了基于验证框架的输入校验,因此我们只需要编写简单的配置文件,框架就会自动帮我们进行服务器客户端校验。有了这套框架,我们无需对代码进行任何修改,仅仅增加一个校验规则文件即可。在想要进行校验的action目录下创建一个ActionName-validation.xml文件作为校验文件,每一个action都有一个校验文件。校验文件的根元素的validators,他可以包括validators或者field,对于每一个需要校验的属性,都要有一个field子元素。校验失败后,会跳转到action的input的result中去,与类型转换有些类似。不仅如此,校验失败的信息也跟类型转换失败信息一样,都封装在FieldError中,放到Action Context中。同样适用s:fielderror来输出错误提示信息。struts2标签表单会自动输出错误信息。校验规则文件如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> <validators> <field name="name"> <field-validator type="requiredstring"> <param name="trim">true</param> <message>you must input name</message> </field-validator> <field-validator type="regex"> <param name="regex"><![CDATA[(\w{4,25})]]></param> <message>you can only input letters and numbers, length between 4 and 25 </message> </field-validator> </field> <field name="pass"> <field-validator type="requiredstring"> <param name="trim">true</param> <message>you must input password</message> </field-validator> <field-validator type="regex"> <param name="regex"><![CDATA[(\w{4,25})]]></param> <message>you can only input letters and numbers, length between 4 and 25 </message> </field-validator> </field> <field name="age"> <field-validator type="int"> <param name="min">1</param> <param name="max">150</param> <message>must between ${min} and ${max}</message> </field-validator> </field> <field name="birth"> <field-validator type="date"> <param name="min">1900-01-01</param> <param name="max">2050-02-21</param> <message>must between ${min} and ${max}</message> </field-validator> </field> </validators>
从配置文件中我们看到,每一个field元素都对应着一个action中需要交验的属性。field下,每一个field-validator都是一条校验规则。如果校验失败,action会返回到input视图,而如果这个视图是之前的s:from的话,在每一个textfield上方,框架会自动输出message信息。这个功能非常方便。
输入登录信息后,显示的message如图所示:
如果想要国际化地显示提示信息,只需要在message属性中使用key属性调用国际化资源中的键值对即可。
<message key="gender"/>
此段代码就标识,当需要显示这条提示信息的时候,架构会去调用国际化文件中(现在action范围找,然后再取包范围,最后在全局国际化资源中找)value为gender的key值,将它显示在input逻辑页面。
使用客户端校验
客户端校验要求表单必须由struts2标签生成,且表单的validate属性为true。此方式校验并不会向服务器提交,地址栏的地址不变。服务器校验与客户端校验在代码上的唯一区别就是form表单中的validate元素。当使用客户端校验的时候,有如下几点需要额外注意:
- 由于不针对action,所以国际化的时候只能采用全局国际化资源。
- 教材上说启用了客户端校验的表单的action,action与namespace要分开写,可是我在测试的时候,分开写报错,不分开反而不报错。
- form的theme属性不能为simple。
- 不能直接访问表单页。可以把这个表单放到web-inf中,使浏览者访问所有资源都经过核心Filter。
两种校验风格
字段优先跟非字段优先是两种校验风格。上面的是字段优先,因为validator下面的元素是field,也就是说先对每个字段分类。如果先指定校验器,然后再向里面添加name为fieldName,值为属性名的param子元素,则为非字段优先。这种风格下,同一个校验器只需要一个message。
短路校验
当其中一个textfield不符合规则的时候,系统就停止校验下面的字段,这种机制叫做短路校验。只需要在validator或者field-validator中设置它的short-circuit为ture即可。
校验文件的搜索规则
因为一个action中会有多个方法,所以每个方法需要不同的校验规则。Struts2框架允许为不同的控制逻辑指定不同的校验规则。此时应该为每一个action的处理方法单独编写校验规则文件。命名规则如下:ActionName-ActionAliasName-validation.xml
这个文件同样是以action实现类的名字开头,但是中间加了一个action别名。这个名字就是struts.xml中action的name属性。加了别名的校验规则,实际上是总的校验规则跟独享规则的总和。也就是说,对于ActionName类中的那个特定方法,ActionName规则生效,而ActionAliasName规则也同样生效。如果发生冲突,则后面的规则会覆盖前面的规则。
各种内建校验器
1. 必填校验器:required。指定的字段必须有值
<field-validator type="required"> <message>information</message> </field-validator>
2. 必填字符串:requiredstring。指定的字符串必须非空长度大于0。它的trim属性用来决定是否在校验前去掉此属性前后空白。
<field-validator type="requiredstring"> <param name="trim">true</param> <message>information</message> </field-validator>
3.整数校验器:int、long、short。验证字段为整数且必须在一定区间内。有max,min两个属性。
4.日期校验器:data。验证日期必须在max与min范围内。
5.表达式校验器:expression。这是一个非字段风格校验器,要求OGNL表达式返回true,否则不通过校验。
6.字段表达式校验器:fieldexpression。要求指定字段满足一个逻辑表达式。这个逻辑表达式通过name为expression的param来制定。
7.邮件地址校验器:email。它只有一个message属性,系统会自动判断字段是不是一个标准的邮件地址。
8.网址校验器:url。基于正则表达式的校验合法网址的校验器。
9.visitor校验器:用于检验action中的复合属性,如action中的user。
10. 转换校验器:conversion。用于检查字段在类型转换过程中是否出现错误。有repopulateField属性,用于指定当类型转换失败进入input页面后,类型转换失败的表单域是否保留原来的信息。
11.字符串长度校验器:stringlength。有minLength和maxLength属性。
12. 正则表达式校验器:regex。用于检查被校验字段是否匹配一个正则表达式。regex参数用于提供正则表达式。caseSensitive用于指定匹配时是否区别大小写。
基于注解的输入校验
这种方法只需要在action中的对应属性的set方法前使用注解即可。
手动完成输入校验
对于一些没有固定逻辑的输入校验,可以采用手动方式。在action中重写validate方法,进行手动校验。不符合规则时,使用addFieldError方法添加错误信息。添加的时候采用键值对的方式添加,以便于我们单独取出某一个值。虽然有了value来标注,但是struts的form标签会输出所有的FieldError信息。架构会判断FieldError是否为空,来决定是否全部符合校验。由于一个action类中可能有很多处理逻辑,而我们仅仅重写了一个validate方法,因此不能用来指定完成哪一个方法的校验。实际上validate会对所有方法进行校验。我们可以重写一系列validateXxx方法,Xxx就是对应的处理逻辑方法。比如说login类中有regist方法,则可以重写validateRegist方法,手动完成对regist方法的校验。