Struts2 自定义验证器

前言
    其实早在四月底就在JR上发表了这篇文章,这次再次搬出来一是为了资料集中,二是做一些修改和更详细的描述.和以往一样入门和介绍就不说了,如何学习在上篇文章Struts2+JFreeChart上有介绍.

正题
1.工程目录结构图:

2.以下依次帖代码:
    a).    web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.FilterDispatcher
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
        <welcome-file>ValidatorDate.jsp</welcome-file>
    </welcome-file-list>
</web-app>

    b).    struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC 
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <include file="struts-validation.xml" />
</struts>

    c).    struts.properties

struts.ui.theme=simple
    d).    struts-validation.xml

<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

    <package name="validationExamples" extends="struts-default"
        namespace="/validation">
        <action name="ValidatorField"
            class="com.tangjun.validator.ValidatorAction">
            <!-- 这里input表示验证失败后指定跳转到什么地方去 -->
            <result name="input" type="dispatcher">/ValidatorDate.jsp</result>
            <result>/success.jsp</result>
        </action>
    </package>
</struts>

    e).    ValidatorAction-validation.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE validators PUBLIC 
          "-//OpenSymphony Group//XWork Validator 1.0.2//EN" 
          "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
    <field name="regexYearField">
        <field-validator type="mydate">
            <param name="maxYear">2008</param>
            <param name="minYear">1900</param>
            <message>
                <![CDATA[ 不是一个有效的年份! ]]>
            </message>
        </field-validator>
    </field>
    <field name="regexMonthField">
        <field-validator type="mydate">
            <message>
                <![CDATA[ 不是一个有效的月份! ]]>
            </message>
        </field-validator>
    </field>
    <field name="regexDayField">
        <field-validator type="mydate">
            <!-- 是否使用正则表达式验证日期 -->
            <param name="isRegex">false</param>
            <!-- 使用自定义正则表达式验证日期 -->
            <!-- 
                <param name="expression"></param>
            -->
            <message>
                <![CDATA[ 当前月份的天数不对! ]]>
            </message>
        </field-validator>
    </field>

</validators>

说明:验证文件需要和Action在同一目录下, 验证文件命名规则:验证文件xxxx-validation.xml,这个xxxx就是你前面action的类名字,xxx-xxx-validation.xml第二个xxx表示是别名.
    f).    validators.xml

<validators>
    <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
    <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>
    <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>
    <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>
    <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>
    <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>
    <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>
    <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>
    <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>
    <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>
    <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>
    <validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>
    <validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>
    <validator name="mydate" class="com.tangjun.validator.DateEx"/>
</validators>

说明:在源码com.opensymphony.xwork2.validator.ValidatorFactory中,在325行至330那一段代码可以看出,如果不能在根目录下找到validators.xml文件,验证框架将调用默认的验证设置,即com.opensymphony.xwork2.
validator.validators目录下default.xml里面的配置信息.最后一个<validator name="mydate" class="com.tangjun.validator.DateEx"/>就是我添加的默认验证器类型.
    g).    ValidatorAction

package com.tangjun.validator;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 验证日期
 * 
 * @author lzl
 * 
 */
public class ValidatorAction extends ActionSupport {

    private static final long serialVersionUID = -4829381083003175423L;

    private Integer regexYearField;

    private Integer regexMonthField;

    private Integer regexDayField;

    public ValidatorAction()
    {
        regexYearField = null;
        regexMonthField = null;
        regexDayField = null;
    }
    
    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }

    public Integer getRegexDayField() {
        return regexDayField;
    }

    public void setRegexDayField(Integer regexDayField) {
        this.regexDayField = regexDayField;
    }

    public Integer getRegexMonthField() {
        return regexMonthField;
    }

    public void setRegexMonthField(Integer regexMonthField) {
        this.regexMonthField = regexMonthField;
    }

    public Integer getRegexYearField() {
        return regexYearField;
    }

    public void setRegexYearField(Integer regexYearField) {
        this.regexYearField = regexYearField;
    }

}

    h).    BeanUtils

package com.tangjun.validator;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BeanUtils {

    /* 默认验证日期正则表达式 */
    private static final String DateExpression = "(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)";

    /**
     * 验证日期合法性(通过抛出错误方式来验证)
     * @param date
     * @return
     */
    public static boolean validatorDate(String date) {
        // 注意这个地方"yyyy-MM-dd"如果设置成了yyyy-mm-dd的话验证将失灵
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 这个的功能是不让系统自动转换 不把1996-13-3 转换为1997-3-1
        sdf.setLenient(false);
        try {
            sdf.parse(date);
            return true;
        } catch (ParseException e) {
            return false;
        }
    }

    /**
     * 使用正则表达式判定日期
     * 
     * @param str
     * @param expression
     * @return
     */
    public static boolean regexValidatorDate(String str, String expression) {
        // 使用正则表达式进行判定
        if (expression == null || expression.trim().length() == 0)
            expression = BeanUtils.DateExpression;
        Pattern pattern;
        // System.out.println(expression);
        pattern = Pattern.compile(expression, 2);
        Matcher matcher = pattern.matcher(str.trim());
        if (!matcher.matches()) {
            return false;
        }
        return true;
    }
}

说明:验证日期的正则表达式就是在网上找的,可以替换成自己的.
    i).    DateEx

package com.tangjun.validator;

import java.util.HashMap;

import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

public class DateEx extends FieldValidatorSupport {

    private static HashMap<String, Integer> map = new HashMap<String, Integer>();

    /* 默认最大年限 */
    private static final Integer MAX_YEAR = 2008;

    /* 默认最小年限 */
    private static final Integer MIN_YEAR = 1900;

    /* 最大年限 */
    private Integer maxYear;

    /* 最小年限 */
    private Integer minYear;

    /* 验证日期的正则表达式 */
    private String expression;

    /* 是否使用正则表达式验证 */
    private Boolean isRegex;
    
    public DateEx() {
        maxYear = null;
        minYear = null;
        expression = null;
        isRegex = false;
    }

    public void validate(Object object) throws ValidationException {

        // 获得字段的名字
        String fieldName = getFieldName();
        // 获得输入界面输入的值
        String value = getFieldValue(fieldName, object).toString();

        if (value == null || value.length() <= 0)
            return;

        if (fieldName.equals("regexYearField"))
            validateYear(value, object);
        else if (fieldName.equals("regexMonthField"))
            validateMonth(value, object);
        else if (fieldName.equals("regexDayField"))
            validateDay(value, object);
    }

    /**
     * 验证年份
     * 
     * @param object
     * @throws ValidationException
     */
    private void validateYear(String value, Object object)
            throws ValidationException {
        /* 设置默认值 */
        if (maxYear == null) {
            maxYear = MAX_YEAR;
        }
        if (minYear == null) {
            minYear = MIN_YEAR;
        }

        Integer temp = null;
        try {
            temp = Integer.valueOf(value);
        } catch (NumberFormatException ex) {
            addFieldErrorEx(getFieldName(), object);
            return;
        }

        if (temp != null) {
            if (temp >= minYear && temp <= maxYear)
                map.put("year", temp);
            else
                addFieldErrorEx(getFieldName(), object);
        }
    }

    /**
     * 验证月份
     * 
     * @param object
     * @throws ValidationException
     */
    private void validateMonth(String value, Object object)
            throws ValidationException {
        try {
            Integer temp = Integer.valueOf(value);
            if (temp != null) {
                if (temp >= 1 && temp <= 12)
                    map.put("month", temp);
                else
                    addFieldErrorEx(getFieldName(), object);
            }
        } catch (NumberFormatException ex) {
            addFieldErrorEx(getFieldName(), object);
            return;
        }
    }

    /**
     * 验证日期
     * 
     * @param object
     * @throws ValidationException
     */
    private void validateDay(String value, Object object)
            throws ValidationException {
        try {
            Integer temp = Integer.valueOf(value);
            if (temp != null) {
                Integer year = map.get("year");
                Integer month = map.get("month");
                
                //直接使用天数
                if(year==null || month==null)
                {
                    return;
                }
                
                // 是否使用正则表达式验证
                if (!isRegex) {
                    if(!BeanUtils.validatorDate(year + "-" + month + "-" + temp))
                        addFieldErrorEx(getFieldName(), object);
                } else {
                    String StrDay = temp < 10 ? "0" + temp.toString() : temp
                            .toString();

                    String StrMonth = month < 10 ? "0" + month.toString()
                            : month.toString();

                    //前面已经验证过了
                    //String StrYear = year < 100 ? year < 10 ? "200" + year: "19" + year : "1" + year;

                    String str = year + "-" + StrMonth + "-" + StrDay;

                    System.out.println("Date:" + str);

                    if (expression == null) {
                        if(!BeanUtils.regexValidatorDate(str, null))
                            addFieldErrorEx(getFieldName(), object);
                    } else {
                        if (expression.trim().length() > 0) {
                            if(BeanUtils.regexValidatorDate(str, expression))
                                addFieldErrorEx(getFieldName(), object);
                        }
                    }
                }
                map.clear();
            }
        } catch (NumberFormatException ex) {
            addFieldErrorEx(getFieldName(), object);
            return;
        }
    }

    /**
     * 控制是否只显示一条报错信息
     * 
     * @param arg0
     * @param arg1
     */
    private void addFieldErrorEx(String arg0, Object arg1) {
        //if (this.getValidatorContext().getFieldErrors().size() == 0)
            addFieldError(arg0, arg1);
    }

    public Integer getMaxYear() {
        return maxYear;
    }

    public void setMaxYear(Integer maxYear) {
        this.maxYear = maxYear;
    }

    public Integer getMinYear() {
        return minYear;
    }

    public void setMinYear(Integer minYear) {
        this.minYear = minYear;
    }

    public String getExpression() {
        return expression;
    }

    public void setExpression(String expression) {
        this.expression = expression;
    }

    public Boolean getIsRegex() {
        return isRegex;
    }

    public void setIsRegex(Boolean isRegex) {
        this.isRegex = isRegex;
    }
}

说明:在DateEx里面,这个时候你就可以参照如IntRangeFieldValidator(反编译源码)等他实现的验证器来写自己的验证器了。这里注意了,你在这个类里面每写一个属性(含get set方法),就对应的一个xxxx-validation.xml这个配置文件里面<param name="expression"></param>这个name的名字了,可以在扩展类里面直接获得了,根据传入参数进行自定义方式验证了。如下object是validate传进来的参数,表示你输入的数据对象:
// 获得字段的名字
String fieldName = getFieldName();
// 获得输入界面输入的值
String value = getFieldValue(fieldName, object).toString();

总结

验证器是拦截器即Interceptor实现的,所以并没有看见任何代码把他们和我的action文件关联起来,他们默认的验证了,这方面可以参考Max On Java的文章.

转载:http://www.cnblogs.com/over140/archive/2007/12/04/982934.html

时间: 2024-10-31 19:38:01

Struts2 自定义验证器的相关文章

struts2自定义验证器(身份证验证)

struts2的验证器是用的xwork里面的验证,自定义验证器就是根据源码继承已有的字段验证器而来.具体步骤如下: 1.展开xwork-2.0.4.jar,com.opensymphony.xwork2.validator.validators目录下有个default.xml,将它复制到项目根目录下改名叫validators.xml. 验证框架首先在根目录下找validators.xml文件,没找到validators.xml文件,验证框架将调用默认的验证设置,即default.xml里面的配置

Angular2表单自定义验证器的实现_AngularJS

本文主要给大家介绍如何判断验证器的结果.在这里,我们就来看看怎样实现一个自定义的验证器. 目标 我们要实现一个验证手机号的验证器,使用的实例还是基于之前的文章里面的实例,也就是用户信息输入的表单页面.我们在手机号的元素上添加一个验证手机号的验证器.然后,如果手机号验证失败,就显示一个错误,页面如下: 这部分教程的代码可以从github获取: git clone https://github.com/Mavlarn/angular2-forms-tutorial 如果要运行,进入项目目录,运行下面

struts2.0-Struts2 验证器 声明式验证 的配置文件中EL的使用

问题描述 Struts2 验证器 声明式验证 的配置文件中EL的使用 解决方案 你是怎么看contextMap和stack的?在页面上debug吗? 解决方案二: 你确定你找的是同一个map或者值栈?contextMap是包装了application,你去看看源码存值方式,是不是有调用完之后,map清key的代码.

struts2自定义拦截器怎么进不去

问题描述 一个破拦截器搞了半天没发现哪里出问题了就是进不去自定义的拦截器里,下面贴代码:struts.xml<?xml version="1.0" encoding="utf-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dt

Struts2 自定义拦截器栈后无法得到表单参数之解决办法

我自定义了一个拦截器,目的是在action执行之前像ValueStack中设置一些属性,代码是这样的: view plaincopy to clipboardprint? HttpServletRequest request=(HttpServletRequest)ActionContext.getContext().get(StrutsStatics.HTTP_REQUEST);        OgnlValueStack stack=(OgnlValueStack)request.getAt

关于Struts2文件上传与自定义拦截器_java

一.访问或添加request/session/application属性 public String scope() throws Exception{   ActionContext ctx = ActionContext.getContext();   ctx.getApplication().put("app", "应用范围");//往ServletContext里放入app   ctx.getSession().put("ses", &q

关于Struts2 表单验证器的错误提示信息显示问题

问题描述 为何默认总是在表单上方显示错误提示信息?我并没有使用 <s:fielderror></s:fielderror> jsp代码如下: <s:form action="loginPro">     <s:textfield name="user.username" key="username" /><s:property value="errors['user.username

Yii2实现自定义独立验证器的方法

本文实例讲述了Yii2实现自定义独立验证器的方法.分享给大家供大家参考,具体如下: 新建一个文件: <?php /** * author : forecho <caizhenghai@gmail.com> * createTime : 2015/7/1 14:54 * description: */ namespace common\helps; use yii\validators\Validator; class ArrayValidator extends Validator {

使用自定义验证组件库扩展 Windows 窗体

window 摘要:数据验证是确保正常的数据捕获以及后续处理和报告的关键步骤.本文介绍了 Windows 窗体固有的程序验证基础结构,并以此为基础开发了用于提供更高效验证功能的自定义验证组件库,该验证功能与使用 ASP.NET 的验证控件相似. 下载 winforms03162004_sample.msi 示例文件. 本页内容 引言 Windows 窗体验证的主要功能 程序验证与声明性验证 建立设计时支持 模仿是最真诚的恭维 必需字段验证程序简介 BaseValidator:分治法 一个放便士,