首页 > 代码库 > Struts2的输入验证(三)-短路验证与非字段验证

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字段在国际化资源文件中对应的名称“年龄”与“数量”:

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

 

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