Struts2的输入验证(三)-短路验证与非字段验证

一、短路验证

若对一个字段使用多个验证器,默认情况下会执行所有的验证。若希望前面的验证器验证没有通过,后面的就不再验证,可以使用短路验证。

1)同一个字段内的多个验证器,如果一个短路验证器验证失败,其他验证器不会继续校验

2)验证程序配置文件中<validator  …/> 元素和 <field-validator  …/> 元素可以指定一个可选的 short-circuit 属性,该属性指定该验证器是否是短验证器,默认值为 false。

1、示例:短路验证器

要求:为age字段配置两个验证器:conversion类型转换验证器和int整数验证器,并将conversion配置为一个短路验证器。

1)JSP页面代码、Action类的代码以及struts.xml的配置与“Struts2的输入验证(一)”中的相同;

2)验证配置文件TestValidationAction-testValidation-validation.xml中段的配置内容为:

<!-- 针对 age 属性进行验证. 基于字段的验证 -->
<field name="age">    
    <!-- 设置短路验证: 若当前验证没有通过, 则不再进行下面的验证 -->
    <field-validator type="conversion" short-circuit="true">
        <message>Conversion Error Occurred</message>
    </field-validator>
    <field-validator type="int">
        <param name="min">20</param>
        <param name="max">60</param>
        <message key="error.int"></message>
    </field-validator>
</field>

在Tomcat中部署运行后的结果如下图:

结果1:视频教程中conversion校验器未设置short-circuit="true"时的结果(其中第一条是类型转换错误的信息,第二条是类型转换校验器的信息,第三条是整形校验器的信息)

结果2:视频教程中conversion校验器设置了short-circuit="true"时的结果(这时,由于类型转换校验器校验未通过,因此没有再执行整形校验器)

 结果3:自己测试的结果(在自己进行测试时发现,在conversion校验器与int校验器配合使用时,无论是否设置conversion校验器的short-circuit属性为true,当输入内容不是一个整数时,都不会有int校验器的提示信息。经过Debug发现,当输入内容不是一个整数时,int校验器执行时,其获得的value值始终为null,因此其就直接返回了一个null,而不再进行校验,也没有添加校验失败的信息。不知道视频中是如何做的,用的都是同样的代码啊。???)

总之,短路验证器的基本使用方法就同示例中一样,具体使用时在参考Struts2的官方文档了。

2、存在的问题

若类型转换失败,默认情况下还会执行后面的拦截器,还会进行验证(在Struts2默认的拦截器栈中,params拦截器在validate拦截器之前)。可以通过修改 ConversionErrorInterceptor 拦截器源代码的方式,使当类型转换失败时不再执行后续的验证拦截器,而直接返回 input 的 result。

方法即在ConversionErrorInterceptor拦截器的intercept()方法return之前添加如下代码:

1 Object action = invocation.getAction();
2 if (action instanceof ValidationAware) {
3     ValidationAware va = (ValidationAware) action;
4     if(va.hasFieldErrors() || va.hasActionErrors()){
5         return "input";
6     }
7 }

即判断fielErrors与actionErrors中是否有值,如果有的话就说明有类型转换错误的信息,就直接返回不在执行后续的拦截器了。

二、非字段验证

即不是针对于某一个字段的验证。

1、示例:非字段验证

要求:校验两次输入的密码是否相同。

1)JSP页面主要代码:

1 <s:debug></s:debug>    
2 <s:actionerror/> <%--注意:由于非字段校验不是针对于某个字段的校验,因此其错误消息不是fieldError类型的,而是actionError类型的,因此要使用actionerror标签来显示--%>
3 <s:form action="testValidation" theme="simple">
4     Password: <s:password name="password"></s:password><br>
5     Password2: <s:password name="password2"></s:password><br>
6     <s:submit></s:submit>
7 </s:form>

2)Action类的代码:

 1 package com.atguigu.struts2.validation.app;
 2 import com.opensymphony.xwork2.ActionSupport;
 3 public class TestValidationAction extends ActionSupport {
 4     private String password;
 5     private String password2;
 6     public String getPassword() {
 7         return password;
 8     }
 9     public void setPassword(String password) {
10         this.password = password;
11     }
12     public String getPassword2() {
13         return password2;
14     }
15     public void setPassword2(String password2) {
16         this.password2 = password2;
17     }
18     public String execute() throws Exception {
19         System.out.println("password: " + password);
20         System.out.println("password2: " + password2);
21         return SUCCESS;
22     }
23 }

3)struts.xml文件的基本配置:

<action name="testValidation" class="com.atguigu.struts2.validation.app.TestValidationAction">
    <result>/success.jsp</result>
    <!-- 若验证失败转向的 input -->
    <result name="input">/validation.jsp</result>
</action>

4)验证程序的配置文件,文件名为:TestValidationAction-validation.xml,配置内容:

<validators>
    <!-- 测试非字段验证-->
    <validator type="expression">
        <param name="expression"><![CDATA[password==password2]]></param><!--注意:这里的表达式要写到CDATA区域(<![CDATA[……..]]>)中,因为其中可能有特殊字符-->
        <message>Password is not equals to password2</message>
    </validator>
</validators>

在Tomcat中部署并运行后,当两次输入的密码不相同时,运行结果如下图:

注意:显示非字段验证的错误消息,使用 s:actionerror 标签:  <s:actionerror/>

2、字段验证 VS 非字段验证

1)字段验证字段优先,可以为一个字段配置多个验证规则。

2)非字段验证验证规则优先。

3)大部分验证规则支持两种验证器,但个别的验证规则只能使用非字段验证,例如表达式验证。 

三、错误消息的重用性

问题:多个字段使用同样的验证规则,可否使用同一条验证消息 ?

1、示例:

要求:页面上有age和count两个字段,这两个字段都是用int验证规则,要求当验证失败时,两者分别显示各自的错误消息。

1)JSP页面的代码:

1 <s:form action="testValidation" theme="simple">
2     Age: <s:textfield name="age" label="Age"></s:textfield>
3     ${fieldErrors.age[0] } <br>
4     Count: <s:textfield name="count"></s:textfield>
5     <s:fielderror fieldName="count"></s:fielderror>
6     <br>
7     <s:submit></s:submit>
8 </s:form>

2)Action类的代码:

 1 package com.atguigu.struts2.validation.app;
 2 import com.opensymphony.xwork2.ActionSupport;
 3 public class TestValidationAction extends ActionSupport {
 4     private Integer age;
 5     private Integer count;
 6     public Integer getAge() {
 7         return age;
 8     }
 9     public void setAge(Integer age) {
10         this.age = age;
11     }
12     public Integer getCount() {
13         return count;
14     }
15     public void setCount(Integer count) {
16         this.count = count;
17     }
18     public String execute() throws Exception {
19         System.out.println("age: " + age);
20         System.out.println("count: " + count);
21         return SUCCESS;
22     }
23 }

3)struts.xml配置文件的内容同短路验证示例。

4)验证程序的配置文件,文件名为:TestValidationAction-validation.xml,配置内容:

 1 <validators>
 2     <field name="age">
 3         <field-validator type="int">
 4             <param name="min">20</param>
 5             <param name="max">60</param>
 6             <message key="error.int"></message>
 7         </field-validator>
 8     </field>
 9     <field name="count">
10         <field-validator type="int">
11             <param name="min">1</param>
12             <param name="max">10</param>
13             <message key="error.int"></message>
14         </field-validator>
15     </field>
16 </validators>

5)添加国际化资源文件i18n.properties,并在其中添加如下内容:

error.int=${getText(fieldName)} needs to be between ${min} and ${max}

age=\u5E74\u9F84 注:这里是年龄
count=\u6570\u91CF 注:这里是数量

在Tomcat中部署并运行结果如下图,注意:这时验证失败消息中分别显示出了age与count字段在国际化资源文件中对应的名称“年龄”与“数量”:

二、配置文件与验证器属性对应关系图解

 

posted @ 2014-08-23 16:35  KnightKitt  阅读(737)  评论(0编辑  收藏  举报