Java后台框架篇--Struts2.0与验证框架

来源:互联网 发布:矢量图软件 手机版 编辑:程序博客网 时间:2024/05/29 08:56

1:Struts2提供了验证框架,功能强大而且简单易用,帮助用户做了很多事情,使得用户不必从头开发。那么一个好的验证框架需要考虑哪些因素呢?

   *验证功能的复用性

    比如都是对一个int数据类型的验证,验证的是它的数据范围,如果验证功能抽象的好,就可以复用同样的验证功能,省去重复开发的麻烦。

   *验证功能的可扩展性

      是不是可以自己扩展验证功能,并保证扩展功能和原有的框架功能一样使用。

    *验证与业务逻辑分离

      在业务开发时,可能需要在业务逻辑不变的情况下修改验证逻辑,比如某个网站要求大于18周岁的公民才能注册,随着业务的开展,要修改为大于15岁的公民才能注册,很显然,这个时候,注册逻辑本身没有改变,但是验证逻辑发生了变化,那么,分离的验证逻辑可以保证在修改验证逻辑的时候,不会为业务逻辑带来麻烦。

 

 2:验证框架入门

     验证需求:用户注册时只需要填写自己的账号、姓名、年龄,其中,账号和姓名必须填写,年龄要求必填而且在18岁以上。

     简单示例:

     页面:register.jsp

      

[html] view plain copy
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <%@ taglib prefix="s" uri="/struts-tags" %>  
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  5. <html>  
  6. <head>  
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  8. <title>Struts2验证框架</title>  
  9. </head>  
  10. <body>  
  11.    <s:form action="register" 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>  

Action的内容:

   

[html] view plain copy
  1. package com.capinfotech.action;  
  2.   
  3. import com.capinfotech.model.UserModel;  
  4.   
  5. public class RegisterAction extends BaseAction {  
  6.   
  7.     private UserModel user = new UserModel();  
  8.   
  9.     public UserModel getUser() {  
  10.         return user;  
  11.     }  
  12.   
  13.     public void setUser(UserModel user) {  
  14.         this.user = user;  
  15.     }  
  16.       
  17.     public String execute() {  
  18.         System.out.println("传人的数据为:" + user.toString());  
  19.         return SUCCESS;  
  20.     }  
  21.       
  22. }  

struts.xml的内容:

 

[html] view plain copy
  1. <action name="register" class="com.capinfotech.action.RegisterAction">  
  2.             <result name="success">/validation/success.jsp</result>  
  3.             <result name="input">/validation/register.jsp</result>  
  4.        </action>  


验证框架的配置文件RegisterAction-validation.xml

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


输出结果:

   

   


验证执行时机:验证发生在execute方法运行之前,在Struts2的params拦截器已经把请求的参数反射的设置到Action的属性之后,所以,验证框架实际上验证的是值栈里面的内容。

验证的结果:如果用户输入的参数完全满足验证条件,则会继续执行execute方法,如果用户输入的参数不满足验证条件,注意:3个验证条件只要有一个验证通不过,就会跳转到这个Action所配置的名为input的Result,所以在struts.xml里最好配置一个名为input的result


3:验证框架的运行原理

   *首先看一下defaultStack包括的拦截器

    

[html] view plain copy
  1. <interceptor-stack name="defaultStack">  
  2.                <interceptor-ref name="exception"/>  
  3.                <interceptor-ref name="alias"/>  
  4.                <interceptor-ref name="servletConfig"/>  
  5.                <interceptor-ref name="i18n"/>  
  6.                <interceptor-ref name="prepare"/>  
  7.                <interceptor-ref name="chain"/>  
  8.                <interceptor-ref name="debugging"/>  
  9.                <interceptor-ref name="scopedModelDriven"/>  
  10.                <interceptor-ref name="modelDriven"/>  
  11.                <interceptor-ref name="fileUpload"/>  
  12.                <interceptor-ref name="checkbox"/>  
  13.                <interceptor-ref name="multiselect"/>  
  14.                <interceptor-ref name="staticParams"/>  
  15.                <interceptor-ref name="actionMappingParams"/>  
  16.                <interceptor-ref name="params">  
  17.                  <param name="excludeParams">dojo\..*,^struts\..*</param>  
  18.                </interceptor-ref>  
  19.                <interceptor-ref name="conversionError"/>  
  20.                <interceptor-ref name="validation">  
  21.                    <param name="excludeMethods">input,back,cancel,browse</param>  
  22.                </interceptor-ref>  
  23.                <interceptor-ref name="workflow">  
  24.                    <param name="excludeMethods">input,back,cancel,browse</param>  
  25.                </interceptor-ref>  
  26.            </interceptor-stack>  

params拦截器和conversionError拦截器在validation拦截器的前面。

params拦截器将请求的参数反射的设置到Action的属性,当然,这时候有可能出错。

conversionError拦截器验证Action的属性是否符合条件。

validation会根据配置文件的配置进行验证,其实,validation验证的是值栈中的内容,而值栈中的内容则来源于请求的参数部分。


验证框架运行流程如下图所示:




4:验证器类型

    *验证谁

    *使用什么条件进行验证

    *不满足条件显示什么结果

    *不满足验证条件时,显示的结果出现在页面的什么位置


    *字段验证器:用来验证提交的表单内的单个字段

    

[html] view plain copy
  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>  
   *field表示是字段验证器,name指示验证哪个字段,每一个field-validator元素是这个字段的一种验证条件,type指示的是验证器,验证错误时,message表示的消息会返回,message元素存在key属性,可以用来引用国际化信息


另一种写法:

  

[html] view plain copy
  1. <validator type="int">  
  2.        <param name="filedName">user.age</param>  
  3.        <param name="min">18</param>  
  4.        <message>年龄必须在18岁以上,您输入的是${user.age}</message>  
  5.    </validator>  

    *动作验证器

    动作验证器应用于整个动作(Action),一般用于验证提交的表单内的多个字段之间的关系,当然也可以验证单个字段

   假定要求输入的账号也为数字,并要求输入的age的值要大于账号的值,那么在验证文件里,可以按照如下写法:

   

[html] view plain copy
  1. <pre name="code" class="html"> <validator type="expression">  
  2.         <param name="expression">  
  3.           <![CDATA[user.name.length() < user.account.length()]]>  
  4.         </param>  
  5.         <message>姓名的长度要比账号的长度小</message>  
  6.     </validator></pre><br>  
  7. <br>  
  8. <p></p>  
  9. <pre></pre>  
  10. <p></p>  
  11. <p>界面输出如下:</p>  
  12. <p>   </p>  
  13. <p><img src="http://hi.csdn.net/attachment/201202/28/0_133040577169VV.gif" alt=""><br>  
  14. </p>  
  15. <p><br>  
  16. </p>  
  17. <p>5:内建验证器</p>  
  18. <p>     </p><pre name="code" class="html"><validators>  
  19.     <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>  
  20.     <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>  
  21.     <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>  
  22.     <validator name="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/>  
  23.     <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/>  
  24.     <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>  
  25.     <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>  
  26.     <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>  
  27.     <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>  
  28.     <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>  
  29.     <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>  
  30.     <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>  
  31.     <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>  
  32.     <validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>  
  33.     <validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>  
  34.     <validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/>  
  35. </validators></pre><br>  
  36. <p></p>  
  37. <p>   *类型转换错误验证器(conversion)</p>  
  38. <p>   *整数验证器(int) 有两个参数min和max</p>  
  39. <p>   *长整型和短整形验证器short和long</p>  
  40. <p>   *日期验证器(date),有两个参数min和max,需要使用同一的格式,比如用MM/DD/YYYY的格式</p>  
  41. <p>   *双精度浮点验证器(double)</p>  
  42. <p>    用来验证一个双精度浮点型参数是否在指定的范围内,如果一个已经被成功转换为double的属性不在验证器指定的范围内,double验证器就会报错。</p>  
  43. <p>       可以接受的参数:</p>  
  44. <p>          *minInclusive用来指定可接收范围的最小值,包含指定值</p>  
  45. <p>          *maxInclusive用来指定可接受范围的最大值,包含给定值</p>  
  46. <p>          *minExclusive用来指定可接受范围的最小值,不包含给定值</p>  
  47. <p>           *maxExclusive用来指定可接受范围的最大值,不包含给定值</p>  
  48. <p>    *邮件验证器(email)</p>  
  49. <p>    *URL验证器(url)</p>  
  50. <p>    *必填验证器(required)</p>  
  51. <p>    *必填字符串验证器(requiredstring):用来验证一个字符串是否非空,即不为null,且长度大于0,trim:是否去掉字符串两边的空白,默认为true</p>  
  52. <p>    *字符串长度验证器(stringlength):用来验证一个字符串的长度是否在指定的长度内</p>  
  53. <p>           可以接受的参数:</p>  
  54. <p>                   *maxLength  minLength   trim</p>  
  55. <p>     *正则表达式(regex): 用来验证一个字符串是否符合一个正则表达式的要求</p>  
  56. <p>            可以接受的参数:</p>  
  57. <p>                   *expression: 必填参数,正则表达式</p>  
  58. <p>                   *caseSensitive:是否检查大小写</p>  
  59. <p>                   *trim:是否去掉字符串两边的空白,默认为true</p>  
  60. <p>       *字段表达式验证器(fieldexpression)和表达式验证器(expression)</p>  
  61. <p>       *访问者验证器(visitor)</p>  
  62. <p>          visitor验证器用于验证Action中的复合属性,可以直接把验证信息放到域对象中去注册,这样就使得同包内的不同Action在验证同一个域对象时,不用注册重复的验证信息。</p>  
  63. <p>        两个属性:</p>  
  64. <p>            *context:引用的域对象验证信息文件上下文名</p>  
  65. <p>            *appendPrefix: 是否在错误信息中添加<message>元素指定的前缀</p>  
  66. <p>   </p>  
  67. <p>6:自定义验证器</p>  
  68. <p>       实现一个不接受中文字符的验证器,比如,在一个网站上进行注册,在输入账号的时候,必须输入英文字符或者是数字,而不接受中文字符,同时还要求验证器可以分辨以下3种情况:</p>  
  69. <p>      *全是非中文字符</p>  
  70. <p>      *全是中文字符</p>  
  71. <p>      *既有中文字符,又有非中文字符</p>  
  72. <p>  </p>  
  73. <p>    实现自定义的验证器</p>  
  74. <p>       要验证一个字符串是否含有中文字符,可以使用比较字符串的字节数和字符数的方式,也就是比较byte的长度和char的长度</p>  
  75. <p>      调用字符串的length方法,可以返回字符串的长度,这时候无论是中文字符还是英文字符都会按照一个字符来返回,也就是得到了字符串的字符数</p>  
  76. <p>      如果把字符串转换成byte[], 然后取其length, 就可以得到字符串的字节数,这时候,中文字符在数组中占两个位置而英文字符在数组中占用一个位置</p>  
  77. <p>     因此,比较字符串的字节数和字符数,就可以知道字符串中是否有中文字符了,如果字节数大于字符数,那么肯定包含了中文字符</p>  
  78. <p>    实现类:</p>  
  79. <p>   </p><pre name="code" class="java">package com.capinfotech.validator;  
  80.   
  81. import com.opensymphony.xwork2.validator.ValidationException;  
  82. import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;  
  83.   
  84. public class ChineseValidator extends FieldValidatorSupport {  
  85.   
  86.     /**  
  87.      * 表示是否包含有中文,有3中模式  
  88.      * none:没有中文  
  89.      * some:含有中文字符,取默认值  
  90.      * all:全是中文字符  
  91.      */  
  92.     private String mode = "some";  
  93.       
  94.     public void setMode(String mode) {  
  95.          this.mode = mode;    
  96.     }  
  97.       
  98.     @Override  
  99.     public void validate(Object object) throws ValidationException {  
  100.     
  101.         //获得字段名  
  102.         final String fieldName = this.getFieldName();  
  103.         //获得字段值  
  104.         final String fieldValue = (String)this.getFieldValue(fieldName, object);  
  105.         //获得字节数  
  106.         final int bytes = fieldValue.getBytes().length;  
  107.         //获得字符数  
  108.         final int chars = fieldValue.length();  
  109.           
  110.         System.out.println("bytes:" + bytes);  
  111.         System.out.println("chars:" + chars);  
  112.           
  113.         if(mode.equals("none")) {  
  114.             //要求全是非中文字符  
  115.             //所以字节数和字符数,两个数字必须相等,不相等则出错  
  116.             if(chars != bytes) {  
  117.                 this.addFieldError(fieldName, object);  
  118.             }  
  119.         } else if(mode.equals("some")) {  
  120.             //现在要求包含有中文字符  
  121.             if(chars == bytes || chars * 2 == bytes) {  
  122.                 this.addFieldError(fieldName, object);  
  123.             }  
  124.         } else if(mode.equals("all")) {  
  125.             if(chars * 2 != bytes) {  
  126.                 this.addFieldError(fieldName, object);  
  127.             }  
  128.         }  
  129.     }  
  130. }  
  131. </pre><br>  
  132. <p></p>  
  133. <p>在src下新建一个validators.xml文件,并把默认的验证器也要包含进来:</p>  
  134. <p></p><pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?>  
  135. <!DOCTYPE validators PUBLIC  
  136.         "-//OpenSymphony Group//XWork Validator Config 1.0//EN"  
  137.         "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">  
  138.   
  139. <!-- START SNIPPET: validators-default -->  
  140. <validators>  
  141.     <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>  
  142.     <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>  
  143.     <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>  
  144.     <validator name="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/>  
  145.     <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/>  
  146.     <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>  
  147.     <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>  
  148.     <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>  
  149.     <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>  
  150.     <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>  
  151.     <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>  
  152.     <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>  
  153.     <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>  
  154.     <validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>  
  155.     <validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>  
  156.     <validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/>  
  157.     <validator name="chinese" class="com.capinfotech.validator.ChineseValidator"/>  
  158. </validators>  
  159. <!--  END SNIPPET: validators-default -->  
  160. </pre><br>  
  161. 使用chinese验证器:<p></p>  
  162. <p></p><pre name="code" class="html"><field name="user.name">  
  163.         <field-validator type="requiredstring">  
  164.              <message>请输入姓名</message>  
  165.         </field-validator>  
  166.           
  167.         <field-validator type="chinese">  
  168.              <param name="mode">none</param>  
  169.              <message>用户账号,只能输入非中文的字符</message>  
  170.         </field-validator>  
  171.     </field></pre><br>  
  172. 输出结果页面:<p></p>  
  173. <p><img src="http://hi.csdn.net/attachment/201202/28/0_1330412834PxBa.gif" alt=""><br>  
  174. </p>  
  175. <p><br>  
  176. </p>  
  177. <p>8:引用验证器返回的错误信息</p>  
  178. <p>      两种方式:</p>  
  179. <p>      *对于字段验证信息错误来说,在<s:form>使用xhtml风格的时候,<s:textfield>标签会将这个字段的错误信息显示在这个文本框的上边</p>  
  180. <p>      *可以使用<s:fielderror>标签来将字段验证错误的错误信息显示在指定位置,如果不指定其filedName属性则会显示所有的错误信息,如果指定了fieldName属性</p>  
  181. <p>     则会显示指定字段的错误,对于动作验证错误,可以使用<s:actionerror>标签,它会把所有的动作验证错误显示在指定的位置</p>  
  182. <p><br>  
  183. </p>  
  184. <p>9:验证器框架的查找顺序</p>  
  185. <p>     *父类-validation.xml</p>  
  186. <p>      *父类-别名-validation.xml</p>  
  187. <p>      *接口-validation.xml</p>  
  188. <p>       *接口-别名-validation.xml</p>  
  189. <p>       *Action类名-validation.xml</p>  
  190. <p>        *Action类名-别名-validation.xml</p>  
  191. <p>其实就是按照父类-->接口-->Action类的顺序</p>  
  192. <p><br>  
  193. </p>  
  194. <p>10:验证器短路</p>  
  195. <p>     当一个字段有多个验证条件的时候,在第一次出现验证错误后,就立即终止验证,后续对这个字段的验证就不再执行了,这就是验证器短路。</p>  
  196. <p>    配置:在验证器的配置上,设置short-circuit属性,其值为true。它可以设置在<field-validator>上,也可以设置在<validator>元素上。</p>  
  197. <p><br>  
  198. </p>  
  199. <p><br>  
  200. </p>  
  201. <p><br>  
  202. </p>  
  203. <p><br>  
  204. </p>  
  205. <p><br>  
  206. </p>  
  207. <p><br>  
  208. </p>  
  209. <p><br>  
  210. </p>  
  211. <p><br>  
  212. </p>  
  213. <p><br>  
  214. </p>  
  215. <p><br>  
  216. </p>  
  217. <p><br>  
  218. </p>  
  219. <p><br>  
  220. </p>  
  221. <p><br>  
  222. </p>  
  223. <p><br>  
  224. </p>  
  225.      
原创粉丝点击