码迷,mamicode.com
首页 > 其他好文 > 详细

Struts2 的 Validation 拦截器

时间:2015-04-07 15:18:12      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

struts2校验有两种实现方法:
    1. 手工编写代码实现(基本验证)
    2. 基于XML配置方式实现(验证框架)
 
  • 手工编写代码实现(基本验证)
I:首先 创建一个EmployeeAction类继承于ActionSupport 对应的页面表单元素就一个empId
 
public class EmployeeAction extends ActionSupport {
 
     private Integer empId;
     public void setEmpId(Integer empId) {
          System. out.println("setEmpId...." );
           this.empId = empId;
     } 
     public String save() {
          System. out.println("save....." );
           employeeService.save(empId );
           return "save-success" ;
     }
     //手动验证 这个方法是从ActionSupport 中继承得到的 因为ActionSupport 类实现          了Validateable的验证接口
    //public class ActionSupport implements Action, Validateable, ValidationAware
 
     @Override
     public void validate() {
           //这个方法是实现ValidationAware接口得到 给empId 属性手动添加一个错误消息 然后返回到浏览器进行显示
           this.addFieldError("empId" , "empId为空值" );
            
          System. out.println("validate....." );
     }  
}
 
基本原理:
 
 I:  this .addFieldError("empId" "empId为空值" );
//ActionSupport 类中
 II: public void addFieldError (String fieldName, String errorMessage) {
        validationAware.addFieldError(fieldName, errorMessage);
  }
ValidationAware的实现类中定义了这个方法接口的内容
III:
public class ValidationAwareSupport implements ValidationAware, Serializable {
 
      private Collection<String> actionErrors ;
      private Collection<String> actionMessages ;
      private Map<String, List<String>> fieldErrors ;
  
   public synchronized void addFieldError (String fieldName, String errorMessage) {
 
        Map<String, List<String>> errors = internalGetFieldErrors();获取一个Map集合
          //根据fieldName获取一个List集合
        List<String> thisFieldErrors = errors.get(fieldName);
 
        if (thisFieldErrors == null) {//判断集合是否为空 为空就创建一个List集合
            thisFieldErrors = new ArrayList<String>();
            errors.put(fieldName, thisFieldErrors);
        }
 
        thisFieldErrors.add(errorMessage);//把fieldName和错误消息 放入集合中
    }
     这个方法说明最终错误消息添加到fieldErrors Map集合中
     private Map<String, List<String>> internalGetFieldErrors() {
        if (fieldErrors == null) {
            fieldErrors = new LinkedHashMap<String, List<String>>();
        }
 
        return fieldErrors ;
    }
}
 
显示在debug中可以看到
 
技术分享
 
总结:
Action中
    *  要继承ActionSupport
    *  重写Validateable接口中的validate()方法 ,在该方法中完成验证
           * 步骤如下:
                 * validate()方法在其他的业务方法之前执行
                 * 验证出错转向的页面
                         struts.xml配置<result name="input">/validate/XXX.jsp</result>  
                         其中input转向是在action中已经定义好的.
                         public static final String INPUT = "input";
                 
                 *   什么时候表示验证出错(转向input所指向的页面)
                         *  this.addFieldError("sss", "错误信息");方法指向的是一个集合
                         *  当集合不为空时,转向错误页面.
 
显示错误Jsp页面:
      使用<s:fielderror/>显示错误消息
 
补充
    validate()方法会校验action中所有与execute方法签名相同的方法。 

*  要校验指定的方法通过重写validateXxx()方法实现, validateXxx()只会校验action中
   方法名为Xxx的方法。其中Xxx的第一个字母要大写。

*  当某个数据校验失败时,调用addFieldError()方法往系统的fieldErrors添加校验失败
   信息(为了使用addFieldError()方法,action可以继承ActionSupport ),如果系统
   的fieldErrors包含失败信息,struts2会将请求转发到名为input的result。

*  在input视图中可以通过<s:fielderror/>显示失败信息。
          validateXxx()方法使用例子:
 
public String add() throws Exception{
     return "success";
}
 
对应的验证方法    
public void validateAdd(){
          //验证代码
}
在ValidationInterceptor拦截器中可以看到以validate开始的方法
 
 
源码中可以看到:
public class ValidationInterceptor extends MethodFilterInterceptor {
 
    private final static String VALIDATE_PREFIX = "validate";
    private final static String ALT_VALIDATE_PREFIX = "validateDo";
    
      
    protected void doBeforeInvocation(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();
        ActionProxy proxy = invocation.getProxy();
 
        String context = this.getValidationContext(proxy);
        String method = proxy.getMethod();
  
        if (declarative ) {
           if (validateAnnotatedMethodOnly ) {
               actionValidatorManager.validate(action, context, method);
           } else {
               actionValidatorManager.validate(action, context);
           }
       }    
        if (action instanceof Validateable && programmatic) {
          
            Exception exception = null;
           
            Validateable validateable = (Validateable) action;
             
            try {
                    //这个和Preparable 拦截器原理相同

                  //在这里获取带有方法前缀的的方法 进行调用
             //  VALIDATE_PREFIX = "validate" ; 
            //ALT_VALIDATE_PREFIX = "validateDo" ;

                PrefixMethodInvocationUtil.invokePrefixMethod(
                                invocation,
                                new String[] { VALIDATE_PREFIX , ALT_VALIDATE_PREFIX });
            }
            catch(Exception e) { 
                exception = e;
            }
            
        }
    }

    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        doBeforeInvocation(invocation); 
        return invocation.invoke();
    } 
}

public class PrefixMethodInvocationUtil {
 
public static void invokePrefixMethod (ActionInvocation actionInvocation, String[] prefixes) {
          Object action = actionInvocation.getAction(); 
          String methodName = actionInvocation.getProxy().getMethod(); 
           if (methodName == null) { 
             methodName = DEFAULT_INVOCATION_METHODNAME;
          } 
          //获取带前缀的方法
          Method method = getPrefixedMethod(prefixes, methodName, action);
           if (method != null) {
               //调用对应的action方法
              method.invoke(action, new Object[0]);
          }
     }
}
//获取带前缀的方法
public class PrefixMethodInvocationUtil {
     
public static Method getPrefixedMethod (String[] prefixes, String methodName, Object action) {
           assert(prefixes != null);
          String capitalizedMethodName = capitalizeMethodName(methodName);
        for (String prefixe : prefixes) {
            String prefixedMethodName = prefixe + capitalizedMethodName;
            try {
                return action.getClass().getMethod(prefixedMethodName, EMPTY_CLASS_ARRAY);
            }
            catch (NoSuchMethodException e) {
                 e
            }
        }
           return null ;
     }

}
输入校验的流程:
 
1。类型转换器对请求参数执行类型转换,并把转换后的值赋给action中的属性。

2。如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器将异常信息封装到fieldErrors里,然后执行第3步。如果类型转换没有出现异常,则直接进入第3步。

3。系统通过反射技术调用action中的validateXxx()方法,Xxx为方法名。

4。调用action中的validate()方法。

5。经过上面4步,如果系统中的fieldErrors存在错误信息(即存放错误信息的集合的size大于0),系统自动将请求转发至名称为input的视图。如果系统中的fieldErrors没有任何错误信息,系统将执行action中的处理方法。

Struts2 的 Validation 拦截器

标签:

原文地址:http://www.cnblogs.com/lflx/p/4398184.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!