所有的MVC框架都需要负责解析HTTP请求参数,并将请求参数传递给控制器组件。但是,HTTP请求参数都是字符串类型,而Java是强类型语言,所以MVC框架必须提供字符串参数和相应数据类型互相转换的功能。
输入校验也是所有Web应用必须处理的问题。因为所有的浏览者都可以自由使用应用,所以收集到的数据非常复杂。可能包括用户的误输入,也可能包含恶意用户的恶意输入,这些都可能导致系统的异常,轻则非正常中断,重者甚至会导致系统崩溃。所以必须将这些异常输入过滤掉,这就是输入校验,也叫数据校验。
系统的类型转换与输入校验的总体流程如下图:
下面将分别对类型转换和输入校验进行总结。
Struts 2中有以下集中类型转换:
(1)Struts 2内建的类型转换器
这种类型转换器主要用于对常用类型进行转换,例如整型(int和Integer)、日期类型(Date)、数组、集合等。这些类型在实际开发中无需进行任何特殊处理。
(2)基于OGNL的类型转换
这种类型转换方法主要用于复合类型。通过OGNL表达式,开发者无需任何特殊处理,就可以对符合类型进行类型转换。不过在使用OGNL表达式方法时,需要注意以下几点:
》需要转换的符合类必须有无参数的构造器,因为Struts 2通过反射来创建一个符合类实例;
》符合类内需要转换类型的属性,需要有相应的setter和getter方法。
(3)通过类型转换文件指定
类型转换文件是一个普通的Properties(.properties)文件。局部类型转换文件的文件名应该为ActionName-conversion.properties形式。这个文件需要放在与Action类文件的相同目录下。文件中通过指定key-value对来指定元素的类型,格式如下:
Element_=
上面是配置列表元素类型的方法。与此类似,Map内的key和value类型也是这样配置。自定义的类型转换器必须实现TypeConverter接口。不过OGNL项目为该接口提供了一个实现类:DefaultTypeConverter,通常可以扩展这个类来实现自定义类型转换器,同时需要重写其中的convertValue()方法。这个方法根据自身的toType参数来判断转换方向,并根据转换方向分别实现。
仅仅提供类型转换器还不够,必须还得在Web应用中注册转换器。注册方式分为局部类型转换器、全局类型转换器和通过注解方式来注册类型转换器。
局部类型转换器只对特定的Action内的指定属性起作用。使用局部类型转换文件指定。其文件配置格式如下:
=
=
其中个参数含义与上相同。
与上一种方法类似,不过这种类型转换器是继承自StrutsTypeConverter抽象类。该抽象类已经实现了convertValue()方法,并将两个转换方向替换成了不同的方法,当把字符串转换成符合类型时,调用convertFromString()方法,把符合类型转换成字符串时,调用convertToString()方法。
输入校验分为客户端校验和服务器端校验。客户端校验主要用于过滤正常用户的误操作,主要通过JavaScript代码完成;服务器端校验是组织非法数据的最后防线,主要通过在应用中编程实现。
Struts 2提供了基于验证框架的输入校验,在这种校验方式下,所有的输入校验只需要编写简单的配置文件,Struts 2的验证框架将会负责进行服务器校验和客户端校验。使用Struts 2的校验框架进行校验,无需对程序代码进行任何改变。
Struts 2中每个Action都有一个校验文件,文件名应该遵循如下规则:
-validation.xml
该文件应该保存在Action的class文件相同的路径之中。字段校验器配置风格遵守如下形式:
参数值
......
校验失败后的提示信息
......
......
非字段校验器配置风格遵守如下形式:
需要被校验的字段
参数值
......
校验失败后的提示信息
......
与类型转换失败相似的是,当输入校验失败后,Struts 2也是自动返回名为“input”的Result。
当一个Action类中包含多个类似execute()方法时,每个方法都是一个处理逻辑。不同的处理逻辑可能需要不同的校验规则。如果需要让Action处理多个请求时,应该在配置时,指定method属性,这样就可以将一个Action处理类配置成多个逻辑Action。这时的校验文件名采用如下形式:
--validation.xml
该文件也需要放在Action的class文件的同一路径下。 在同时存在
更进一步,如果存在两个Action:BaseAction和ChildAction,其中ChildAction继承了BaseAction,那么系统对校验文件的搜索顺序如下:
Struts 2搜索规则文件是从上而下的,实际用的校验规则是所有校验规则的总和。如果两个校验文件中有冲突,则后面文件的校验规则会覆盖前面的。
校验器的执行顺序有如下规则:
校验器短路的原则如下:
使用注解来指定验证规则,只要使用验证器注解修饰Action里各成员变量对应的setter方法即可,同时将该Action相同路径下的校验规则我呢见删除。
Sturts 2也允许通过手动方式完成自定义校验,来满足一些特殊的校验需求。
手动完成输入校验有两种方法,一个是重写validate()方法,一个是重写validateXxx()方法。
总的来看,Struts 2的输入校验需要经过以下几个步骤: