基于Struts 2校验器的校验可以完成绝大部分输入校验,但这些校验器都具有固定的校验逻辑,无法满足一些特殊的校验规则。对于一些特殊的校验要求,可能需要在Struts 2中进行手动校验。Struts 2提供了良好的可扩展性,从而允许通过手动方式完成自定义校验。
1.重写validate()方法
本应用一样采用前面的注册页面,但现在我们要求name请求参数的值必须包含crazyit字符串(这个要求其实也可通过正则表达式校验器完成,此处仅仅是示范)。现在我们通过重写ActionSupport类的validate()方法来进行这种校验。
下面的示例将对上面的注册应用进行改进,为上面的Web应用增加Struts 2支持。增加Struts 2支持后,将通过如下的Action来处理用户请求。下面的Action仅仅重写了ActionSupport类的validate方法。
下面是重写validate()方法后的RegistAction代码。
程序清单:codes\04\4.2\overrideValidate\WEB-INF\src\org\crazyit\app\action\RegistAction.java
- public class RegistAction extends ActionSupport
- {
- private String name;
- private String pass;
- private int age;
- private Date birth;
- //省略了4个属性的setter和getter方法
- ...
- public void validate()
- {
- System.out.println("进入validate方法进行校验"
- + name);
- //要求用户名必须包含crazyit子串
- if(!name.contains("crazyit"))
- {
- addFieldError("user" ,
- "您的用户名必须包含crazyit!");
- }
- }
- }
上面的粗体字代码重写了validate方法,在validate方法中,一旦发现校验失败,就把校验失败提示通过addFieldError方法添加进系统的FieldError中,这与类型转换失败后的处理是完全一样的。除此之外,程序无须做额外的处理,如果Struts 2发现系统的FieldError不为空,将会自动跳转到input逻辑视图,因此依然必须在struts.xml文件中为该Action的input逻辑视图指定视图资源。
除此之外,为了在input视图对应的JSP页面中输出错误提示,应该在该页面中增加如下代码:
- <!-- 输出类型转换失败提示和校验失败提示 -->
- <s:fielderror/>
上面的<s:fielderror/>标签专门负责输出系统的FieldError信息,也就是输出系统的类型转换失败提示和输入校验的失败提示。
如果在输入页面输入的用户名不包含crazyit字符串,我们将会看到如图4.19所示的界面。
图4.19 重写validate方法完成输入校验
在上面的validate方法中,如果校验失败,我们直接添加了校验失败的提示信息,并没有考虑国际化的问题。但这并不是太大的问题,因为ActionSupport类里包含了一个getText方法,该方法可以取得国际化信息。
2.重写validateXxx()方法
前面已经介绍过了,Struts 2的Action类里可以包含多个处理逻辑,不同的处理逻辑对应不同的方法。即Struts 2的Action类里定义了几个类似于execute的方法,只是方法名不是execute。
如果我们的输入校验只想校验某个处理逻辑,也就是仅校验某个处理方法,则重写validate方法显然不够,validate()方法无法准确知道需要校验哪个处理方法。实际上,如果我们重写了Action的validate方法,则该方法会校验所有的处理逻辑。
为了实现校验指定处理逻辑的功能,Struts 2的Action允许提供一个validateXxx()方法,其中xxx即是Action对应的处理逻辑方法。
下面对上面的Action进行改写,为该Action增加regist,并增加validateRegist()方法。修改后的RegistAction类代码如下。
程序清单:codes\04\4.2\validateXxx\WEB-INF\src\org\crazyit\app\actionRegistAction.java
- public class RegistAction extends ActionSupport
- {
- //该Action的4个属性
- private String name;
- private String pass;
- private int age;
- private Date birth;
- //此处省略4个属性的setter和getter方法
- ...
- public String regist()
- {
- return SUCCESS;
- }
- public void validate()
- {
- …
- }
- public void validateRegist()
- {
- System.out.println("进入validateRegist方法进行校验"
- + name);
- //要求用户名必须包含.org子串
- if(!name.contains(".org"))
- {
- addFieldError("user" ,
- "您的用户名必须包含.org!");
- }
- }
- }
实际上,上面的validateRegist方法与前面的regist方法大致相同,此处仅仅是为了讲解如何通过提供validateXxx方法来实现只校验某个处理逻辑。
为了让该Action的regist方法来处理用户请求,必须在struts.xml文件中指定该方法。struts.xml文件的代码如下。
程序清单:codes\04\4.2\validateXxx\WEB-INF\src\struts.xml
- <?xml version="1.0" encoding="GBK"?>
- <!-- 指定Struts 2配置文件的DTD信息 -->
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
- "http://struts.apache.org/dtds/struts-2.1.7.dtd">
- <struts>
- <!-- 指定Struts 2应用的国际化资源文件 -->
- <constant name="struts.custom.i18n.resources" value="mess"/>
- <!-- 指定Struts 2应用编码的字符集 -->
- <constant name="struts.i18n.encoding" value="GBK"/>
- <package name="lee" extends="struts-default">
- <!-- 定义处理用户请求的regist Action,使用.RegistAction的regist
- 方法处理用户请求 -->
- <action name="registPro" class="org.crazyit.app.action.RegistAction"
- method="regist">
- <result name="input">/WEB-INF/content/regist.jsp</result>
- <result>/WEB-INF/content/show.jsp</result>
- </action>
- <action name="*">
- <result>/WEB-INF/content/{1}.jsp</result>
- </action>
- </package>
- </struts>
在上面名为registPro的Action中,指定使用RegistAction的regist方法处理用户请求。如果浏览者再次向registPro提交请求,该请求将由RegistAction的regist处理逻辑处理,那么不仅validate()方法会进行输入校验,validateRegist()方法也会执行输入校验。
如果我们在本应用的regist.jsp页面中输入不符合要求,将看到如图4.20所示的页面。
从图4.20中可以看出,当用户向regist方法发送请求时,该Action内的validate方法和validateRegist方法都会起作用,而且validateRegist方法首先被调用。
前面已经介绍过了,不管用户向Action的哪个方法发送请求,Action内的validate方法都会被调用。如果该Action内还有该方法对应的validateXxx方法,则该方法会在validate方法之前被调用。
通过上面示例的介绍,我们不难发现Struts 2的输入校验需要经过如下几个步骤:
类型转换器负责对字符串的请求参数执行类型转换,并将这些值设置成Action的属性值。
在执行类型转换过程中可能出现异常,如果出现异常,将异常信息保存到ActionContext中,conversionError拦截器负责将其封装到FieldError里,然后执行第3步;如果转换过程没有异常信息,则直接进入第3步。
使用Struts 2应用中所配置的校验器进行输入校验。
通过反射调用validateXxx()方法,其中Xxx是即将处理用户请求的处理逻辑所对应的方法。
调用Action类里的validate()方法。
如果经过上面5步都没有出现FieldError,将调用Action里处理用户请求的处理方法;如果出现了FieldError,系统将转入input逻辑视图所指定的视图资源。图4.21显示了Struts 2表现层数据的整套处理流程。
本文转自fkJava李刚 51CTO博客,原文链接http://blog.51cto.com/javaligang/887139: ,如需转载请自行联系原作者