《研磨struts2》第十章 验证框架 之 10.2 验证框架入门

10.2  验证框架入门

10.2.1准备基础资源

通过示例来初步学习一下如何使用Struts2的验证框架,只简单的做这样一个用户注册的功能:用户注册的时候只需要填写自己的账号、姓名、年龄,其中,账号和姓名要求必填,年龄要求必填而且在18岁以上。

1:封装用户注册信息的域对象

ta�Ktr�-�8%�t;text-justify-trim:punctuation'>

10.2.1准备基础资源

 

java代码:
  1. public class UserModel {  
  2.     private String account;  
  3.     private String name;  
  4.     private int age;  
  5.     public String getAccount() {  
  6.         return account;  
  7.     }  
  8.     public void setAccount(String account) {  
  9.         this.account = account;  
  10.     }  
  11.     public String getName() {  
  12.         return name;  
  13.     }  
  14.     public void setName(String name) {  
  15.         this.name = name;  
  16.     }  
  17.     public int getAge() {  
  18.         return age;  
  19.     }  
  20.     public void setAge(int age) {  
  21.         this.age = age;  
  22.     }  
  23.     public String toString(){  
  24.         return "account="+account+",name="+name+",age="+age;  
  25.     }  
  26. }  

2:用户的注册页面

在这个页面上,使用<s:form>表单标签来提交信息,不指定其风格,默认使用xhtml。这个jsp为WebContent/validate/register.jsp,示例如下:

 

java代码:
  1. <%@ page language="java" contentType="text/html; charset=gb2312"  pageEncoding="gb2312"%>  
  2. <%@taglib prefix="s" uri="/struts-tags" %>  
  3. <html>  
  4. <head>  
  5. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">  
  6. <title>Insert title here</title>  
  7. </head>  
  8. <body>  
  9. 用户注册  
  10. <hr>  
  11. <s:form action="/registerAction.action" method="post">  
  12.     <s:textfield name="user.account" label="账号"/>  
  13.     <s:textfield name="user.name" label="姓名"/>  
  14.     <s:textfield name="user.age" label="年龄"/>  
  15.     <s:submit value="注册"/>  
  16. </s:form>  
  17. </body>  
  18. </html>  

3:注册用的Action

       只是简单实现:接到注册页面传入的数据,并在execute方法中将它打印出来,示例如下:

 

java代码:
  1. public class RegisterAction extends ActionSupport{  
  2.     public UserModel user = new UserModel();  
  3.     public String execute() throws Exception {  
  4.         System.out.println("传入的数据为="+user);  
  5.         return SUCCESS;  
  6.     }     
  7. }  

4:注册成功后的结果页面

       这个页面非常简单,就是简单的显示注册成功的信息,示例如下:

 

java代码:
  1. <%@ page language="java" contentType="text/html; charset=gb2312"  pageEncoding="gb2312"%>  
  2. <%@taglib prefix="s" uri="/struts-tags" %>  
  3. <html>  
  4. <head>  
  5. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">  
  6. <title>Insert title here</title>  
  7. </head>  
  8. <body>  
  9. 恭喜您注册成功!  
  10. </body>  
  11. </html>  

5:在struts.xml中添加配置


java代码:
  1. <package name="helloworld" extends="struts-default">  
  2.     <action name="registerAction" class="cn.javass.validate.RegisterAction">  
  3.         <result>/validate/success.jsp</result>  
  4.     </action>  
  5. </package>  

所有的工作都准备完了,来运行测试一下,先访问注册页面,然后填入合适的数据,点击注册看看是否能正确提交,并跳转到成功页面。应该是没有问题的,那么,接下来就在这个示例的基础上,来使用验证框架。

10.2.2初会验证框架

在上一节的例子中,并没有使用验证框架。这时候,用户的任何输入都会被RegistAction所接收。

       现在来加入验证框架,非常简单,只需要添加一个xml,这个xml命名为Action类名-validation.xml,放在需要验证的Action类同包下,其内容为这个Action的execute方法运行前要对用户的输入进行的各种验证。

很显然,需要在RegisterAction同包下,新建一个RegisterAction-validation.xml的文件,示例内容如下:

 

java代码:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE validators PUBLIC  
  3.         "-//OpenSymphony Group//XWork Validator 1.0//EN"        "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">  
  4.           
  5. <validators>  
  6.     <field name="user.account">  
  7.         <field-validator type="requiredstring">  
  8.             <message>请填入账号</message>  
  9.         </field-validator>  
  10.     </field>  
  11.     <field name="user.name">  
  12.         <field-validator type="requiredstring">  
  13.             <message>请填入姓名</message>  
  14.         </field-validator>  
  15.     </field>  
  16.     <field name="user.age">  
  17.         <field-validator type="int">  
  18.             <param name="min">18</param>  
  19.             <message>年龄必须在18岁以上</message>  
  20.         </field-validator>  
  21.     </field>  
  22. </validators>   

在这个示例里面:

  • 用户的账号字段(user.account)要求必填。这个要求对应着<validators>元素中,name属性为user.account的<field >子元素。

l         在这个<field>元素中,只有一个<field-validator>子元素,说明这个字段只需要使用一个条件进行验证。

l         <field-validator>元素的type属性为requiredstring,说明这个字段必填,而验证框架不管用户填的什么。

l         <field-validator>元素的<message>子元素是当这个验证条件不满足的时候,验证框架返回的错误信息。

  • 用户的姓名字段(user.name)也要求必填,与上个字段验证条件相似,就不再赘述了。
  • 用户的年龄字段(user.age)要求必须填入一个不小于18的整数。这个要求对应着<validators>元素中,name属性为user.age的<field >子元素。

l         在这个<field>元素中,只有一个<field-validator>子元素,说明这个字段只需要使用一个条件进行验证。

l         <field-validator>元素的type属性为int,说明这个字段必填,而且必须是个整数。

l         <field-validator>元素的<param>子元素name属性为min,值为18,指明了这个整数的最小值为18。

l         <field-validator>元素的<message>子元素是当这个验证条件不满足的时候,验证框架返回的错误信息

很简单吧,每个字段是否需要验证,需要什么样的验证,验证是否需要更明确的参数等等信息,都是通过配置来指定。

       那么,在添加了验证文件之后,什么时候运行呢?验证通不过怎么办呢?

  • 验证的时机。验证发生在execute方法运行之前,在Struts2的params拦截器已经把请求的参数反射的设置到Action的属性之后。所以,验证框架实际上验证的是值栈内的值。
  • 验证的结果。如果用户输入的参数完全满足验证条件,则会继续执行execute方法,如果用户输入的参数不满足验证条件,注意:三个验证条件只要有一个验证通不过,就会跳转到这个Action所配置的名为input的Result。

示例里面还没有名为input的Result,一般情况下,input结果都是在验证不成功的情况下,返回到原来提交的页面,所以,稍稍修改一下struts.xml,加上这个input的配置:

 

java代码:
  1. <package name="helloworld" extends="struts-default">  
  2.     <action name="registerAction" class="cn.javass.validate.RegisterAction">  
  3.         <result name="input">/validate/register.jsp</result>  
  4.         <result>/validate/success.jsp</result>  
  5.     </action>  
  6. </package>  

再次运行测试,不过,这次故意不填姓名,并把年龄填成12,运行结果为:

《研磨struts2》第十章 验证框架 之 10.2 验证框架入门_第1张图片

图10.1 验证框架入门

       可以看到,不满足验证条件的姓名和年龄的错误信息,会从RegistAction-validation.xml中读出,并显示在对应文本框的上面。

10.2.3验证框架的运行原理

通过前面的示例会发现,要加上验证框架是那么的简单惬意,只需要增加一个验证文件,再为Action配置一个名为input的Result就可以了。但是验证框架到底是如何运行的呢?接下来就来分析一下验证框架的运行流程。

1:相关的拦截器      

       在Struts2中,要为Action配置相应的验证功能,需要引用validation拦截器,可以在struts-default.xml中找到与validation拦截器相关的配置,示例如下:

 

java代码:
  1. <package name="struts-default" abstract="true">  
  2.     <interceptors>  
  3.         <interceptor name="validation"   
  4. s="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>  
  5.         <interceptor-stack name="defaultStack">  
  6. .  
  7.             <interceptor-ref name="params">  
  8.               <param name="excludeParams">dojo\..*,^struts\..*</param>  
  9.             </interceptor-ref>  
  10.             <interceptor-ref name="conversionError"/>  
  11.             <interceptor-ref name="validation">  
  12.                 <param name="excludeMethods">input,back,cancel,browse</param>  
  13.             </interceptor-ref>  
  14. .  
  15.         </interceptor-stack>  
  16.    </interceptors>  
  17.   
  18.    <default-interceptor-ref name="defaultStack"/>  
  19. </package>  

首先,validation拦截器被声明在了defaultStack拦截器栈里,因此,我们的Action引用了这个拦截器,因为我们的Action没有配置拦截器,那就使用默认的defaultStack。

       其次,在validation拦截器之前,又声明了params拦截器和conversionError拦截器。这三个拦截器都在Action的execute方法执行前运行,分别实现:

  • params拦截器将请求的参数反射的设置入Action的属性。当然,这时候有可能出错,比如,要将“18a”这个字符串放入一个int属性的时候,肯定会出错。
  • conversionError拦截器在params拦截器出错的情况下,把出现的错误放在值栈中。
  • validation拦截器验证Action的属性是否符合条件。

在以上的三个功能中,最关键的是validation拦截器,它会根据验证文件的配置进行验证,但是到底验证的是谁呢?

其实validation验证的是值栈里面的相应内容,而值栈里面的这些相应内容则来源于请求的参数部分。

2:validation拦截器操作值栈

通过示例来说明validation拦截器验证的是值栈的内容。

示例大概需要进行三步修改:

  • 修改一下UserModel,为它的age属性设置默认值,比如为12,示例如下:
java代码:
  1. private int age = 12;  

修改一下注册页面,去掉user.age这个文本框,但是在前面加上显示错误信息部分:

 

java代码:
  1. 用户注册  
  2. <hr>  
  3. <s:fielderror/>  
  4. <hr>  
  5. <s:form action="/registerAction.action">  
  6.     <s:textfield name="user.account" label="账号"/>  
  7.     <s:textfield name="user.name" label="姓名"/>  
  8.     <s:submit value="注册"/>  
  9. </s:form>  

       注意:加上的<s:fielderror/>即为显示错误信息的标签。

修改一下验证文件,让返回的错误信息中直接引用值栈的内容,只需要修改其中关于user.age的部分:

 

java代码:
  1. <field name="user.age">  
  2.     <field-validator type="int">  
  3.         <param name="min">18</param>  
  4.         <message>年龄必须在18岁以上,您输入的是${user.age}</message>  
  5.     </field-validator>  
  6. </field>  

在message中引用${user.age}即为使用ognl引用值栈的内容,当前的值栈的顶层对象为Action对象,所以${user.age}实为引用Action对象的user属性的age属性。

       这时候,再访问注册页面,发现已经没有年龄的文本框了。提交的时候填入账号和姓名,这时候发现运行的结果为:

《研磨struts2》第十章 验证框架 之 10.2 验证框架入门_第2张图片

图10.2 验证validation拦截器验证值栈的内容

有些朋友可能会问,页面并没有传入user.age参数,validation拦截器怎么说输入的值是12呢?

这就是因为在UserModel的age属性上设置了age的默认值为12,而且提交请求的时候也没有提交user.age这个参数,所以,Struts2默认就把12放入值栈,因此,验证操作的user.age的数据也就是12了。

       这也变相说明:validation拦截器操作的是值栈而不仅仅是请求的参数了。不过,这绝对是个好事,值栈可是个聚宝盆,里面什么都有,比如,要验证填入的参数是不是和session中的某个值相等,都是可以做到的了。

       另外一个就是注意在验证的配置文件里面,引用值栈的语法,是“${}”,里面写的同样是OGNL表达式。

       验证完之后,请大家将域对象UserModel和注册页面还原,以备后需使用,验证文件不用还原,保留就可以了。

3:类型转换出错的情况

       在详细描述验证框架的运行流程前,还需要思考一个问题,如果在进行类型转换的时候出错了怎么办?

       比如在user.age中填入的是个字符串,如“18a”,不能转换为数字怎么办?

       params拦截器不能把18a转换为数字,不能操作值栈中user.age对应的值,而user.age就保持其初始值,即Action对象的user属性的age属性的初始值,如果没有设置默认值的话,它就是0;接下来conversionError拦截器把这个错误放入值栈,注意:这个错误和拦截器验证得到的有关user.age的错误一样,姑且称之为字段验证错误;最后validation拦截器框架仍然执行user.age验证,这时值栈中user.age的值就是0。所以,综上所述,关于user.age会得到两条错误,“类型转换错误”和“填入的年龄小于18”。

       运行测试一下,现在填入账号和姓名,但是年龄填入18a,得到的结果为:

《研磨struts2》第十章 验证框架 之 10.2 验证框架入门_第3张图片

图10.3 用户输入无法正确类型转换时验证器框架的工作情况

4:验证框架的运行流程  

把上面的知识总结一下,用流程图来描述验证器框架的运行流程,如下图所示:

《研磨struts2》第十章 验证框架 之 10.2 验证框架入门_第4张图片

图10.4 验证器框架运行流程

 

私塾在线网站原创《研磨struts2》系列

转自请注明出处:【http://sishuok.com/forum/blogPost/list/0/4091.html

欢迎访问http://sishuok.com获取更多内容

你可能感兴趣的:(struts2)