zoukankan      html  css  js  c++  java
  • Struts2之Validator

    Struts2中提供了数据校验验证数据例如验证邮件、数字等。验证方式有3种:一是通过validate()方法,二是通过Xml,三是使用注解方式。

    一、初始化

    首先定义一个User类

    package com.cyw.test;
    
    import java.util.Date;
    
    public class User {
    
        private String name;
        private int age;
        private String email;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getEmail() {
            return email;
        }
        public void setEmail(String email) {
            this.email = email;
        }
        public Date getBirthDay() {
            return birthDay;
        }
        public void setBirthDay(Date birthDay) {
            this.birthDay = birthDay;
        }
        private Date birthDay;
    
    }
    View Code

    二、validate()方法验证

    可以在继承了ActionSupport的Action中重写validate()来进行验证。validate()方法会在execute()方法执行前执行,仅当数据校验正确,才执行execute()方法, 如错误则将错误添加到fieldErrors域中,如果定义的Action中存在多个逻辑处理方法,且不同的处理逻辑需要不同的校验规则,这种情况下validate()会对所有处理逻辑使用相同的校验规则,为了实现不同的校验逻辑,需要通过validateX()方法,其中X表示处理逻辑的方法名,如果有错误系统会返回result name="input"的页面,所以需要在action中定义一个input的result。我昨天就困在这个地方好久。问了我大学同学才解决,为了这个validate()验证昨晚一点多都没睡,虽然SSH框架现在不流行,特别是前几天struts2报了一个远程bug,不过想着既然学java了,就系统的学一遍吧。

    1.validate()方法

    package com.cyw.test;
    
    import java.text.ParsePosition;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class ValidatorAction extends ActionSupport {
        private User user;
        private List<User>userList=new ArrayList<User>();
        public List<User> getUserList() {
            return userList;
        }
        public void setUserList(List<User> userList) {
            this.userList = userList;
        }
        @Override
        public String execute() throws Exception {
            if(user==null || this.hasFieldErrors())
            {
                return "regist";
            }
            else
            {
                return "success";
            }
            
        }
        public String addUser()
        {
            userList.add(user);
            return "success";
        }
        
        private static final long serialVersionUID = 1L;
    
        public User getUser() {
            return user;
        }
        public void setUser(User user) {
            this.user = user;
        }
        
    
        @Override
        public void validate() {
            if(user!=null)
            {
                if(!dataPass( user.getName(),"^[A-Za-z][A-Za-z1-9_-]+$"))
                {
                    addFieldError("user.name", "用户名(字母开头 + 数字/字母/下划线)");
                    
                }
                if(!dataPass(String.format("%d", user.getAge()) ,"(?:[1-9][0-9]?|1[01][0-9]|120)"))
                {
                    addFieldError("user.name", "年龄0-120之间");
                    
                }
                Date startDate=strToDate("1900-01-01");
                Date endDate=strToDate("2017-01-01");
                if(user.getBirthDay().before(startDate) || user.getBirthDay().after(endDate) )
                {
                    addFieldError("birthDay", "出生日期在1900-01-01至2017-01-01之间。");
                    
                }
                
                if(!dataPass(user.getEmail(),"^[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\.){1,3}[a-zA-z\-]{1,}$"))
                {
                    addFieldError("email", "邮箱格式不符合");
                    
                }
            }
        
        }
        private  Date strToDate(String strDate)
        {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            ParsePosition pos = new ParsePosition(0);
            Date strtodate = formatter.parse(strDate, pos);
            return strtodate;    
        }
        private boolean dataPass(String str,String regEx)
        {
            Pattern pattern=Pattern.compile(regEx,Pattern.CASE_INSENSITIVE);
            Matcher matcher =pattern.matcher(str);
            return matcher.matches();
        }
    
        
    }
    View Code
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    <struts>
             <package name="default" namespace="" extends="struts-default">
            <action name="regist"  class="com.cyw.test.ValidatorAction">
                <result name="regist">/register.jsp</result>
                <result name="success">/success.jsp</result>
                <result name="input">/register.jsp</result>    
            </action>
        </package>
    </struts>
    View Code
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
        <%@ taglib uri="/struts-tags" prefix="struts" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>注册页面</title>
    </head>
    <body>
    <struts:fielderror key="name"></struts:fielderror>
        <struts:form action="regist" method="post">
        <struts:textfield name="user.name" label="用户名"></struts:textfield>
        <br/>  
         <struts:textfield name="user.age" label="年龄"></struts:textfield>
        <br/>    
        <struts:textfield name="user.birthDay" label="出生日期"></struts:textfield>
       
        <br/>  
              <struts:textfield name="user.email" label="邮箱"></struts:textfield>
        <br/> 
        <struts:submit value="注册"></struts:submit>   
        </struts:form>   
    </body>
    </html>
    View Code

    2.validateX()方法

    package com.cyw.test;
    
    import java.text.ParsePosition;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class ValidatorAction extends ActionSupport {
        private User user;
        private List<User>userList=new ArrayList<User>();
        public List<User> getUserList() {
            return userList;
        }
        public void setUserList(List<User> userList) {
            this.userList = userList;
        }
    
        public String addUser()
        {
            if(user==null)
            {
                return "regist";
            }
            userList.add(user);
            
            return "success";
        }
        
        private static final long serialVersionUID = 1L;
    
        public User getUser() {
            return user;
        }
        public void setUser(User user) {
            this.user = user;
        }
        public void validateAddUser() {
            if(user!=null)
            {
                if(!dataPass( user.getName(),"^[A-Za-z][A-Za-z1-9_-]+$"))
                {
                    addFieldError("user.name", "用户名(字母开头 + 数字/字母/下划线)");
                    
                }
                if(!dataPass(String.format("%d", user.getAge()) ,"(?:[1-9][0-9]?|1[01][0-9]|120)"))
                {
                    addFieldError("user.name", "年龄0-120之间");
                    
                }
                Date startDate=strToDate("1900-01-01");
                Date endDate=strToDate("2017-01-01");
                if(user.getBirthDay().before(startDate) || user.getBirthDay().after(endDate) )
                {
                    addFieldError("birthDay", "出生日期在1900-01-01至2017-01-01之间。");
                    
                }
                
                if(!dataPass(user.getEmail(),"^[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\.){1,3}[a-zA-z\-]{1,}$"))
                {
                    addFieldError("email", "邮箱格式不符合");
                    
                }
            }
        
        }
        private  Date strToDate(String strDate)
        {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            ParsePosition pos = new ParsePosition(0);
            Date strtodate = formatter.parse(strDate, pos);
            return strtodate;    
        }
        private boolean dataPass(String str,String regEx)
        {
            Pattern pattern=Pattern.compile(regEx,Pattern.CASE_INSENSITIVE);
            Matcher matcher =pattern.matcher(str);
            return matcher.matches();
        }
    
        
    }
    View Code
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    <struts>
             <package name="default" namespace="" extends="struts-default">
            <action name="regist"  class="com.cyw.test.ValidatorAction" method="addUser">
                <result name="regist">/register.jsp</result>
                <result name="success">/success.jsp</result>
                <result name="input">/register.jsp</result>    
            </action>
        </package>
    </struts>
    View Code
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
        <%@ taglib uri="/struts-tags" prefix="struts" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>注册页面</title>
    </head>
    <body>
    <struts:fielderror key="name"></struts:fielderror>
        <struts:form action="regist" method="post">
        <struts:textfield name="user.name" label="用户名"></struts:textfield>
        <br/>  
         <struts:textfield name="user.age" label="年龄"></struts:textfield>
        <br/>    
        <struts:textfield name="user.birthDay" label="出生日期"></struts:textfield>
       
        <br/>  
              <struts:textfield name="user.email" label="邮箱"></struts:textfield>
        <br/> 
        <struts:submit value="注册"></struts:submit>   
        </struts:form>   
    </body>
    </html>
    View Code

    二、XML验证

    使用validate方法校验时,如果Web应用中存在大量Action就需要多次重写validate方法,因此可以使用XWork的validator框架来对Struts2进行数据校验,减少代码量。在action包下创建验证文件XXX-validation.xml,注:当一个Action中有多个业务处理方法是,命名规则为:actionName-methodName-validation.xml,其中actionName为Action类名,methodName为Action中某个业务处理方法的方法名,并且文件的搜索顺序与方式一种validate()和validateX()一样。

    这里先注释掉Action的验证方法,然后新增一个xml验证文件,最后要在form中增加validate="true"

    <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE validators PUBLIC
              "-//Apache Struts//XWork Validator 1.0.3//EN"
              "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
    
    <validators>
    <field name="user。name">
        <field-validator type="regex">
        <param name="expression"><![CDATA[(w{4,20})]]></param>
        <message>用户名必须在4到20 之间,且必须是字母或者数字</message>
        </field-validator>
    </field>
    <field name="user.email">
        <field-validator type="email">
            <message>你的电子邮件地址必须是一个有效的电邮地址</message>
        </field-validator>
    </field>
    <field name="user.age">
        <field-validator type="int">
            <param name="min">1</param>
            <param name="max">120</param>
        <message>年纪必须在1到120之间</message>
        </field-validator>
    </field>
    <field name="user.birthDay" >
        <field-validator type="date" short-circuit="true">
            <param name="min">1900-01-01</param>
            <param name="max">2050-02-21</param>
           <message>生日在${min}到${max}之间</message>
        </field-validator>
    </field>
    </validators>
    View Code

     

    这里遗留了两个问题,一是错误信息不是一次全部显示出来,如上面两个图先显示两个错误提示,然后将显示的修改正确之后又显示其他的,这为什么不是全部显示出来呢?二是在Xml中使用正则表达式验证怎么不起作用,这个也是个遗留的问题,先把这两个问题放在这里,等以后再问下其他人,如果哪位读者知道原因也希望留言告诉博主,先谢过了。

    三、注解

    1.Validations Annotation的使用

    Validations中定义了一些验证器的数组,用于存放验证规则,定义如下
     public @interface Validations {
     //自定义校验器数组
        public CustomValidator[] customValidators() default {};
        //字段转换错误校验器数组
        public ConversionErrorFieldValidator[] conversionErrorFields() default {};
        //日期范围校验器
        public DateRangeFieldValidator[] dateRangeFields() default {};
     //Email校验器
        public EmailValidator[] emails() default {};
     //字段表达式校验器
        public FieldExpressionValidator[] fieldExpressions() default {};
     //整数范围校验器
        public IntRangeFieldValidator[] intRangeFields() default {};
     //必填字段校验器
        public RequiredFieldValidator[] requiredFields() default {};
     //必填字符串校验器
        public RequiredStringValidator[] requiredStrings() default {};
     //字符串长度校验器
        public StringLengthFieldValidator[] stringLengthFields() default {};
     //URL校验器
        public UrlValidator[] urls() default {};
        //带条件的Vistor校验器
        public ConditionalVisitorFieldValidator[] conditionalVisitorFields() default {};
     //Vistor校验器
        public VisitorFieldValidator[] visitorFields() default {};
     //正则表达式校验器
        public RegexFieldValidator[] regexFields() default {};
     //表达式校验器
        public ExpressionValidator[] expressions() default {};
    }

    RequiredStringValidator —— 必填字符串校验器
     校验要求:指定字段不能为null且字符串长度大于0
     参数: fieldName:校验字段名
        trim:校验时取出字符串两边的空格,默认为true
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
       
    RequiredFieldValidator —— 必填校验器
     校验要求:指定字段不能为null
     参数: fieldName:校验字段名
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
    IntRangeFieldValidator —— 整数范围校验器
     校验要求:int、long、short字段的整数值在指定的范围内
     参数:min:指定最小值,可选,没有则不检查最小值
        max:指定最大值,可选,没有则不检查最大值
        fieldName:校验字段名
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
       
    DateRangeFieldValidator —— 日期范围校验器
     校验要求:日期在指定的范围内  
     参数:min:指定最小值,可选,没有则不检查最小值
        max:指定最大值,可选,没有则不检查最大值 
        fieldName:校验字段名
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
          
    EmailValidator —— Email地址校验器
     校验要求:指定的字段为Email地址
     参数: fieldName:校验字段名
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
       
    ExpressionValidator —— 表达式校验器
     校验要求:指定的ONGL表达式返回true。
     参数: expression:ONGL表达式  
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
          
    UrlValidator —— URL校验器
     校验要求:校验指定的字段值是否为合法的URL
     参数: fieldName:校验字段名
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
       
    StringLengthFieldValidator —— 字符串长度校验器
     校验要求:字符串长度在指定的范围内
     参数:minLength:指定最小长度,可选,没有则不检查最小长度
        maxLength:指定最大长度,可选,没有则不检查最大长度 
        trim:校验时取出字符串两边的空格,默认为true
        fieldName:校验字段名
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
        
    ConversionErrorFieldValidator —— 转换错误校验器
     校验要求:校验指定字段是否发生类型转换错误
     参数: fieldName:校验字段名
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
       
    VisitorFieldValidator —— Vistor校验器
     说明:普通校验器只能校验基本数据类型和字符串类型,该校验器可以校验对象里面的属性。
     参数:context:用于校验的context
        appendPrefix: 校验发生错误时是否在错误信息中添加前最消息
        fieldName:校验字段名
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
       
    RegexFieldValidator —— 正则表达式校验器
     校验要求:指定字段匹配指定的正则表达式
     参数:expression:正则表达式
        fieldName:校验字段名
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
       
    ConditionalVisitorFieldValidator —— 带条件的Vistor校验器
     验证要求:在条件不满足时,和Vistor校验器功能一样,条件满足则不执行Vistor校验
     参数: fieldName:校验字段名
        message:校验失败时的消息
        key:校验失败时返回i18n中指定名称的消息
       
    CustomValidator —— 自定义校验器 
     校验器:自定义校验器 

    举例:

    package com.cyw.test;
    
    import java.text.ParsePosition;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import com.opensymphony.xwork2.ActionSupport;
    import com.opensymphony.xwork2.validator.annotations.Validations;
    import com.opensymphony.xwork2.validator.annotations.*;
    
    public class ValidatorAction extends ActionSupport {
        private User user;
        private List<User>userList=new ArrayList<User>();
        public List<User> getUserList() {
            return userList;
        }
        public void setUserList(List<User> userList) {
            this.userList = userList;
        }
    
        @Validations(
                emails={@EmailValidator(fieldName="user.email",message="邮件字段的格式不对")},
                conversionErrorFields={@ConversionErrorFieldValidator(fieldName="user.age",message="年龄输入的值转换错误")},
                intRangeFields={@IntRangeFieldValidator(fieldName="user.age",min="0",max="120",message="年龄范围为0到120")},
               
                dateRangeFields={@DateRangeFieldValidator(fieldName="user.birthDay",min="1900-01-01",max="2017-03-30",message="日期输入不正确")},
               
               
                regexFields={@RegexFieldValidator(regexExpression="^[A-Za-z][A-Za-z1-9_-]+$",fieldName="user.name",message="用户名(字母开头 + 数字/字母/下划线)")}
              
                )
        public String addUser()
        {
            if(user==null)
            {
                return "regist";
            }
            userList.add(user);
            
            return "success";
        }
        
        private static final long serialVersionUID = 1L;
    
        public User getUser() {
            return user;
        }
        public void setUser(User user) {
            this.user = user;
        }
    }
    View Code

    结论:

          1.Action类中使用Validations Annotation定义验证。
       2.Action中,可以在方法上、类上定义验证Annotations,所有的验证器都将同时作用在映射为Action的方法上。
       3.Action中有多个方法被映射为Action时,类上和方法上所有定义的验证Annotations都将作用在每个映射为Action的方法上。
       4.Action中校验失败时,返回input逻辑视图
       5.可以使用@SkipValidation跳过所有的验证检查,包括自身方法定义的校验器。
       6.可以在Action映射中使用如下代码跳过校验检查
         <interceptor-ref name="validation">
             <param name="validateAnnotatedMethodOnly">true</param>
         </interceptor-ref>

    遗留问题修改:

    上面遗留了一个问题,在xml中来做验证时正则表达式不起作用,保存之后突然想到在注解中用下面的代码来表示的

     regexFields={@RegexFieldValidator(regexExpression="^[A-Za-z][A-Za-z1-9_-]+$",fieldName="user.name",message="用户名(字母开头 + 数字/字母/下划线)")}

    看着参数名和xml中配置的不一样,会不会是参数名错误呢?因为我在网上查的有的用regex或expression,不过都说在提问说不起作用,我怀疑是不是参数名有问题,甚至在一些教程网http://www.yiibai.com/struts_2/xml_based_validators.html上用的也是expression,报着试一试的态度用regexExpression试一试,没想到还成功了。应该将上面用xml验证name的地方改成这样子。

    <field name="user.name">
    <field-validator type="regex">
    <param name="regexExpression"><![CDATA[(^[A-Za-z][A-Za-z1-9_-]+$)]]></param>
    <message>用户名(字母开头 + 数字/字母/下划线)</message>
    </field-validator>
    </field>

  • 相关阅读:
    POJ 2513 (Trie树+欧拉通路+并查集判断连通)
    归并排序及序列逆序数
    POJ 2442 Sequence (堆+K路归并)
    POJ 2513 (Trie树+欧拉通路+并查集判断连通)
    J2EE概述
    J2EE概述
    J2EE概述
    学习视频资料下载论坛
    J2EE概述
    J2EE概述
  • 原文地址:https://www.cnblogs.com/5ishare/p/6641756.html
Copyright © 2011-2022 走看看