Struts2 之 Validation 拦截器 基于XML配置方式实现(验证框架)

基于XML配置方式实现输入校验

I:定义Action

*  要继承ActionSupport或者实现Validateable接口:

II:配置struts_validate.xml文件

*  验证出错转向的页面
                struts.xml配置<result name=“input”>/validate/loginxml.jsp</result>  
                其中input转向是在action中已经定义好的.

III:配置验证的xml文件

*  验证的xml文件的规范在xwork-core-2.1.6.jar包下的:xwork-validator-1.0.3.dtd
            *  验证文件的命名
                 *   在这个校验文件中,对action中字符串类型的username属性进行验证,
                      首先要求调用trim()方法去掉空格,然后判断用户名是否为空。
                 *    该文件需要和action类放在同一个包下,文件的取名应遵守
                        ActionClassName-validation.xml规则,其中ActionClassName为action
                     的简单类名,-validation为固定写法。
                 *     例如:如果Action类为ValidateXmlAction. 那么该文件
                        的取名应为:ValidateXmlAction-validation.xml
                 *      ValidateXmlAction-validation.xml为文件的配置如下

<!DOCTYPE validators PUBLIC

"-//Apache Struts//XWork Validator 1.0.2//EN"

"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd" >

<validators>

<field-validator type= "requiredstring">

<param name= "trim">true</param >

<message key= "error.required"></message >

</field-validator>

<field-validator type= "email">

如果需要国际化,可以为message
                             指定key属性,key的值为属性文件中的key。

<message key= "error.email"></message >

</field-validator>

</validators>

<validators>: 根元素
<field>:指定action中要校验的属性,name属性指定将被验证的表单字段的名字
<field-validator>:指定校验器, type 指定验证规则
     上面指定的校验器requiredstring是由系统提供的,系统提供了能满足大部分验证需求
      的校验器,这些校验器的定义可以在xwork-2.x.jar中的
      com.opensymphony.xwork2.validator.validators下的default.xml中找到。
<param>:子元素可以向验证程序传递参数
<message>:子元素为校验失败后的提示信息,如果需要国际化,可以为message
                   指定key属性,key的值为属性文件中的key。

校验器案例:

equired  必填校验器
<field-validator type="required">
       <message>性别不能为空!</message>
</field-validator>

requiredstring  必填字符串校验器
<field-validator type="requiredstring">
       <param name="trim">true</param>
       <message>用户名不能为空!</message>
</field-validator>

stringlength:字符串长度校验器
<field-validator type="stringlength">
     <param name="maxLength">10</param>
     <param name="minLength">2</param>
     <param name="trim">true</param>
     <message><![CDATA[产品名称应在2-10个字符之间]]></message>
</field-validator>

nt:整数校验器
<field-validator type="int">
     <param name="min">1</param>
     <param name="max">150</param>
     <message>年龄必须在1-150之间</message>
</field-validator>

字段OGNL表达式校验器
<field name="imagefile">
     <field-validator type="fieldexpression">
          <param name="expression"><![CDATA[imagefile.length() <= 0]]></param>
          <message>文件不能为空</message>
     </field-validator>
</field>

email:邮件地址校验器
<field-validator type="email">
     <message>电子邮件地址无效</message>
</field-validator>

regex:正则表达式校验器
<field-validator type="regex">
     <param name="expression"><![CDATA[^13\d{9}$]]></param>
     <message>手机号格式不正确!</message>
</field-validator>

2:基于XML配置方式对指定action方法实现输入校验

当校验文件的取名为ActionClassName-validation.xml时,会对 action中的所有处理方法实施输入验证。如果你只需要对action中的某个action方法实施校验,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,其中ActionName为struts.xml中action的名称。例如:在实际应用中,常有以下配置:
<action name="user_*" class="cn.itcast.action.UserAction" method="{1}">
     <result name="success">/WEB-INF/page/message.jsp</result>
     <result name="input">/WEB-INF/page/addUser.jsp</result>
</action>
UserAction中有以下两个处理方法:
public String add() throws Exception{
   ....
}
public String update() throws Exception{
   ....
}
要对add()方法实施验证,校验文件的取名为: UserAction-user_add-validation.xml
要对update()方法实施验证,校验文件的取名为: UserAction-user_update-validation.xml

基于XML校验的一些特点

当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件时,系统按下面顺序寻找校验文件:
1。AconClassName-validation.xml
2。ActionClassName-ActionName-validation.xml
系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于处理方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。

当action继承了另一个action,父类action的校验文件会先被搜索到。假设UserAction继承BaseAction, UserAction在struts.xml的配置如下:
<action name="user" class="cn.itcast.action.UserAction" method="{1}">
     .....
</action>
访问上面名为user的action,系统先搜索到BaseAction-validation.xml, BaseAction-user-validation.xml,接着搜索到UserAction-validation.xml, UserAction-user-validation.xml。校验规则是这四个文件的总和。

分析验证原理:

在xwork-core-2.1.6.jar包下包含一个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="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/>
    <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/>
    <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="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/>
</validators>

也就是说当我们在配置文件中写好的配置 系统会自动去找对应的类方法进行验证

补充理解小点:

I:系统加载验证的XML文件  读取到DefaultActionValidatorManager类中的ValidatorConfig进行使用

II:<result name="input">/WEB-INF/page/addUser.jsp</result>在struts2中这个input怎么返回的。
查看源码:
在ValidationInterceptor 验证拦截器查看得知:

public class ValidationInterceptor extends MethodFilterInterceptor {
    private boolean alwaysInvokeValidate = true;
    public void setAlwaysInvokeValidate(String alwaysInvokeValidate) {
            this.alwaysInvokeValidate = Boolean.parseBoolean(alwaysInvokeValidate);
    }
    protected void doBeforeInvocation(ActionInvocation invocation) throws Exception {

        if (action instanceof Validateable && programmatic) {

            Validateable validateable = (Validateable) action;
            try {

               //把验证错误信息添加在fieldErrors Map集合中 但并没有返回 “input”
                PrefixMethodInvocationUtil.invokePrefixMethod(
                                invocation,
                                new String[] { VALIDATE_PREFIX, ALT_VALIDATE_PREFIX });
            }
          //这个默认为true
            if (alwaysInvokeValidate ) {
               //以上是把验证错误信息放入到一个fieldErrors Map集合中后继续执行
                validateable.validate();
            }

        }
    }
    protected String doIntercept(ActionInvocation invocation) throws Exception {
          //方法执行完成 继续执行下一个拦截器  DefaultWorkflowInterceptor
        doBeforeInvocation(invocation);
        return invocation.invoke();
    }
}
在DefaultWorkflowInterceptor拦截器中可以查看源码得知input返回值在这里进行返回

public class DefaultWorkflowInterceptor extends MethodFilterInterceptor {

    private static final long serialVersionUID = 7563014655616490865L;

    private static final Logger LOG = LoggerFactory.getLogger(DefaultWorkflowInterceptor .class );

    private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];

    private String inputResultName = Action.INPUT;

    public void setInputResultName(String inputResultName) {
        this.inputResultName = inputResultName;
    }
    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();
          //首先盘对请求的action是否实现了 ValidationAware的接口
        if (action instanceof ValidationAware) {
            ValidationAware validationAwareAction = (ValidationAware) action;
            //这一步 判断fieldErrors Map集合中是否有错误
            if (validationAwareAction.hasErrors()) {
                 //如果Map集合不为空就赋值resultName 为input
                String resultName = inputResultName;

                if (action instanceof ValidationWorkflowAware) {
                    resultName = ((ValidationWorkflowAware) action).getInputResultName();
                } 

                if (annotation != null) {
                    if (!annotation.methodName().equals("" )) {
                        Method method = action.getClass().getMethod(annotation.methodName());
                        resultName = (String) method.invoke(action);
                    } else {
                        resultName = annotation.resultName();
                    }
                }
               //在这里返回 input;
                return resultName;
            }
        }
     //如果Map集合 为空就继续执行
        return invocation.invoke();
    }

}

//DefaultWorkflowInterceptor类继承自MethodFilterInterceptor  实现了doIntercept方法
//当doIntercept返回input时进行接收
public abstract class MethodFilterInterceptor extends AbstractInterceptor { 

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        if (applyInterceptor(invocation)) {
          //接收到 input 进行向上返回
            return doIntercept(invocation);
        }
        return invocation.invoke();
    }

    protected abstract String doIntercept(ActionInvocation invocation) throws Exception;

}
//DefaultActionInvocation 管理调度拦截器的执行和返回值(个人理解)
public class DefaultActionInvocation implements ActionInvocation {

    public String invoke() throws Exception {
        String profileKey = "invoke: ";
        try {
            UtilTimerStack.push(profileKey);
           //执行拦截器
            if (interceptors .hasNext()) {

                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack. push(interceptorMsg);
                try {
     //在这里进行最终的接受拦截器的返回值 “input”
   resultCode     =interceptor.getInterceptor().intercept(DefaultActionInvocation. this);
                            }
                finally {
                    UtilTimerStack. pop(interceptorMsg);
                }
            } else {
                resultCode = invokeActionOnly();
            } 

                if (proxy .getExecuteResult()) {
                    //执行<result name="input">/WEB-INF/page/addUser.jsp</result>
                    executeResult();
                }

                executed = true;
            }

            return resultCode ;
        }
        finally {
            UtilTimerStack. pop(profileKey);
        }
    }
 private void executeResult() throws Exception {
        result = createResult();
         // getResultCode也就是获取到了input
        String timerKey = "executeResult: " + getResultCode();
        try {
            UtilTimerStack. push(timerKey);
            if (result != null) {
                result.execute( this);
            }
        }
    }
} 

以上都是个人单步调试看到的 能力有限 仅限个人理解
时间: 2024-08-26 15:29:15

Struts2 之 Validation 拦截器 基于XML配置方式实现(验证框架)的相关文章

Struts2 的 Validation 拦截器

struts2校验有两种实现方法:     1. 手工编写代码实现(基本验证)     2. 基于XML配置方式实现(验证框架) 手工编写代码实现(基本验证) I:首先 创建一个EmployeeAction类继承于ActionSupport 对应的页面表单元素就一个empId public class EmployeeAction extends ActionSupport { private Integer empId; public void setEmpId(Integer empId)

转载 - Struts2基于XML配置方式实现对action的所有方法进行输入校验

出处:http://www.cnblogs.com/Laupaul/archive/2012/03/15/2398360.html 使用基于XML配置方式实现输入校验时,Action也需要继承ActionSupport,并且提供校验文件,校验文件和action类放在同一个包下,文件的取名格式为:ActionClassName-validation.xml.ActionClassName为action的简单类名,-validation为固定写法.如果Action类为cn.validate.acti

Spring3.2 中 Bean 定义之基于 XML 配置方式的源码解析

Spring3.2 中 Bean 定义之基于 XML 配置方式的源码解析 本文简要介绍了基于 Spring 的 web project 的启动流程,详细分析了 Spring 框架将开发人员基于 XML 定义的 Bean 信息转换为 Spring 框架的 Bean Definition 对象的处理过程,向读者展示了 Spring 框架的奥妙之处,可以加深开发人员对 Spring 框架的理解. 0 评论: 秦 天杰, 软件工程师, IBM China 2013 年 9 月 02 日 内容 在 IBM

Bean的基于XML配置方式

基于XML配置 Beans.xml <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" 1.默认命名空间 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2.xsi标准命名空间,用于指定自定义命名空间的Sc

Spring 基于xml配置方式的事务

参考前面的声明式事务的例子:http://www.cnblogs.com/caoyc/p/5632198.html 我们做了相应的修改.在dao中和service中的各个类中,去掉所有注解标签.然后为为每个字段提供一个setXxx()方法 最后就是配置applicationContext.xml文件了.内容如下: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http:/

Spring 基于xml配置方式的事务(14)

参考前面的声明式事务的例子:http://www.cnblogs.com/caoyc/p/5632198.html 我们做了相应的修改.在dao中和service中的各个类中,去掉所有注解标签.然后为为每个字段提供一个setXxx()方法 最后就是配置applicationContext.xml文件了.内容如下: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http:/

Spring 基于xml配置方式的AOP

我们具体用代码来说明: 1.ArithmeticCalculator.java 1 package com.proc; 2 3 public interface ArithmeticCalculator { 4 int add(int i, int j); 5 int sub(int i, int j); 6 7 int mul(int i, int j); 8 int div(int i, int j); 9 } 2.ArithmeticCalculatorImpl.java 实现接口Arit

Struts2基于XML配置方式实现对Action方法进行校验

JavaWeb框架(2) 使用XML对Action方法进行校验方式有两种,一种是对Action的所有方法进行校验,另一种是对Action指定方法进行校验. 对Action的所有方法进行校验: 步骤: 1.创建Action需要继承ActionSupport 2.提供校验的xml文件,该文件和action放在同一个包下 校验文件的取名格式为:PersonAction-validation.xml,其中PersonAction为action的简单类名,-valication为固定写法 示例: Acti

cors跨域请求问题 关于spring -springmvc -mybatis .基于xml配置方式

1:场景还原 今天要写一个方法, 需求是  在购物车服务上,  调用一个个人中心的方法 ,用到了 跨域请求. 我就在个人中心的 上面写了个方法, 并在springMVC.xml中,配置了 配合完成以后 写了一个ajax 测试接口.却总是出现跨域失败 未完待续...... 原文地址:https://www.cnblogs.com/sansy/p/9926537.html