AnnotationValidationInterceptor拦截器处于defaultStack第十七的位置,主要是用于数据校验的,该拦截器继承自ValidationInterceptor拦截器增加了在方法上使用注解取消校验功能。ValidationInterceptor又继承自MethodFilterInterceptor。前面继承自MethodFilterInterceptor的拦截器中都没有讲MethodFilterInterceptor,在AnnotationValidationInterceptor配置中传递了一个名为excludeMethods的参数,这个参数就是提交到MethodFilterInterceptor中的,用于指定哪些方法是不需要进行校验的。所以这里先讲解MethodFilterInterceptor拦截器,下面是MethodFilterInterceptor的intercept源码:
@Override public String intercept(ActionInvocation invocation) throws Exception { if (applyInterceptor(invocation)) { return doIntercept(invocation); } return invocation.invoke(); }
protected boolean applyInterceptor(ActionInvocation invocation) { String method = invocation.getProxy().getMethod(); //真正判断的方法是MethodFilterInterceptorUtil.applyMethod方法,把排除的方法集合与包含的方法集合与Action要执行的方法名传入 //该方法把字符串转成了正则表达式对该方法进行匹配,逻辑不难,但判断代码比较多,所以讲到这吧... boolean applyMethod = MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, method); if (log.isDebugEnabled()) { if (!applyMethod) { log.debug("Skipping Interceptor... Method [" + method + "] found in exclude list."); } } return applyMethod; }
<interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref>
protected String doIntercept(ActionInvocation invocation) throws Exception { //获取当前执行的Action Object action = invocation.getAction(); if (action != null) {//如果Action不为null Method method = getActionMethod(action.getClass(), invocation.getProxy().getMethod());//获取Action要执行的方法 //获取Action中加了SkipValidation注解的方法集合 Collection<Method> annotatedMethods = AnnotationUtils.getAnnotatedMethods(action.getClass(), SkipValidation.class); if (annotatedMethods.contains(method)) return invocation.invoke();//如果当前执行的方法有SkipValidation注解则不进行校验,调用下一个拦截器 //检测是否有覆盖父类标有SkipValidation注解的方法 Class clazz = action.getClass().getSuperclass();//获取父类字节码 while (clazz != null) { annotatedMethods = AnnotationUtils.getAnnotatedMethods(clazz, SkipValidation.class);//获取父类标有SkipValidation注解的方法集合 if (annotatedMethods != null) {//如果方法不为null //如果当前要执行的方法是覆盖了父类的方法,而父类方法标有SkipValidation注解,则当前方法也不进行校验 for (Method annotatedMethod : annotatedMethods) { if (annotatedMethod.getName().equals(method.getName()) && Arrays.equals(annotatedMethod.getParameterTypes(), method.getParameterTypes()) && Arrays.equals(annotatedMethod.getExceptionTypes(), method.getExceptionTypes())) return invocation.invoke();//调用下一个拦截器 } } clazz = clazz.getSuperclass();//获取父类字节码 } } //如果要进行校验,继续调用父类的doIntercept方法 return super.doIntercept(invocation); }
@Override protected String doIntercept(ActionInvocation invocation) throws Exception { doBeforeInvocation(invocation);//调用doBeforeInvocation方法 return invocation.invoke();//调用下一个拦截器 } doBeforeInvocation(invocation)方法源码: protected void doBeforeInvocation(ActionInvocation invocation) throws Exception { Object action = invocation.getAction();//获取当前执行的Action ActionProxy proxy = invocation.getProxy();//获取ActionProxy对象 //the action name has to be from the url, otherwise validators that use aliases, like //MyActio-someaction-validator.xml will not be found, see WW-3194 String context = proxy.getActionName();//获取Action名称 String method = proxy.getMethod();//获取执行Action的方法名称 //省略... //declarative默认为true if (declarative) { if (validateAnnotatedMethodOnly) {//validateAnnotatedMethodOnly默认为false actionValidatorManager.validate(action, context, method); } else { actionValidatorManager.validate(action, context);//所以执行这里 } } //如果Action实现了Validateable接口,ActionSupport实现了Validateable接口 if (action instanceof Validateable && programmatic) {//programmatic默认为true Exception exception = null; //强转 Validateable validateable = (Validateable) action; if (LOG.isDebugEnabled()) { LOG.debug("Invoking validate() on action "+validateable); } try {//调用有validate,validateDo前缀的方法 PrefixMethodInvocationUtil.invokePrefixMethod( invocation, new String[] { VALIDATE_PREFIX, ALT_VALIDATE_PREFIX }); } catch(Exception e) { // If any exception occurred while doing reflection, we want // validate() to be executed LOG.warn("an exception occured while executing the prefix method", e); exception = e; } //alwaysInvokeValidate默认为true,总是调用Action的validate方法 if (alwaysInvokeValidate) { validateable.validate(); } if (exception != null) { // rethrow if something is wrong while doing validateXXX / validateDoXXX throw exception; } } }