`
zsmud
  • 浏览: 71667 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

struts2 拦截器原理

阅读更多
struts2 拦截器堆栈是由一个ActionInvocation的东东递归调用执行的过程,
在堆栈的底部是由action,PreResultListener,Result组成的东东。


/**   
 * @throws ConfigurationException If no result can be found with the returned code   
 */   
public String invoke() throws Exception {    
    String profileKey = "invoke: ";    
    try {    
        UtilTimerStack.push(profileKey);    
                
        if (executed) {    
            throw new IllegalStateException("Action has already executed");    
        }    
        // 依次调用拦截器堆栈中的拦截器代码执行    
        if (interceptors.hasNext()) {    
            final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();    
            UtilTimerStack.profile("interceptor: "+interceptor.getName(),     
                    new UtilTimerStack.ProfilingBlock<String>() {    
                        public String doProfiling() throws Exception {    
                         // 将ActionInvocation作为参数,调用interceptor中的intercept方法执行    
                            resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);    
                            return null;    
                        }    
            });    
        } else {    
            resultCode = invokeActionOnly();    
        }    
   
        // this is needed because the result will be executed, then control will return to the Interceptor, which will    
        // return above and flow through again    
        if (!executed) {    
            // 执行PreResultListener    
            if (preResultListeners != null) {    
                for (Iterator iterator = preResultListeners.iterator();    
                    iterator.hasNext();) {    
                    PreResultListener listener = (PreResultListener) iterator.next();    
                            
                    String _profileKey="preResultListener: ";    
                    try {    
                            UtilTimerStack.push(_profileKey);    
                            listener.beforeResult(this, resultCode);    
                    }    
                    finally {    
                            UtilTimerStack.pop(_profileKey);    
                    }    
                }    
            }    
   
            // now execute the result, if we're supposed to    
            // action与interceptor执行完毕,执行Result    
            if (proxy.getExecuteResult()) {    
                executeResult();    
            }    
   
            executed = true;    
        }    
   
        return resultCode;    
    }    
    finally {    
        UtilTimerStack.pop(profileKey);    
    }    
}  
/**
 * @throws ConfigurationException If no result can be found with the returned code
 */
public String invoke() throws Exception {
    String profileKey = "invoke: ";
    try {
     UtilTimerStack.push(profileKey);
      
     if (executed) {
      throw new IllegalStateException("Action has already executed");
     }
        // 依次调用拦截器堆栈中的拦截器代码执行
     if (interceptors.hasNext()) {
      final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
      UtilTimerStack.profile("interceptor: "+interceptor.getName(), 
        new UtilTimerStack.ProfilingBlock<String>() {
      public String doProfiling() throws Exception {
                         // 将ActionInvocation作为参数,调用interceptor中的intercept方法执行
          resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
          return null;
      }
      });
     } else {
      resultCode = invokeActionOnly();
     }

     // this is needed because the result will be executed, then control will return to the Interceptor, which will
     // return above and flow through again
     if (!executed) {
            // 执行PreResultListener
      if (preResultListeners != null) {
       for (Iterator iterator = preResultListeners.iterator();
        iterator.hasNext();) {
        PreResultListener listener = (PreResultListener) iterator.next();
         
        String _profileKey="preResultListener: ";
        try {
          UtilTimerStack.push(_profileKey);
          listener.beforeResult(this, resultCode);
        }
        finally {
          UtilTimerStack.pop(_profileKey);
        }
       }
      }

      // now execute the result, if we're supposed to
            // action与interceptor执行完毕,执行Result
      if (proxy.getExecuteResult()) {
       executeResult();
      }

      executed = true;
     }

     return resultCode;
    }
    finally {
     UtilTimerStack.pop(profileKey);
    }
}



从源码中,我们可以看到,我们之前提到的Struts2的Action层的4个不同的层次,在这个方法中都有体现,他们分别是:拦截器(Interceptor)、Action、PreResultListener和Result。在这个方法中,保证了这些层次的有序调用和执行。由此我们也可以看出Struts2在Action层次设计上的众多考虑,每个层次都具备了高度的扩展性和插入点,使得程序员可以在任何喜欢的层次加入自己的实现机制改变Action的行为。

在这里,需要特别强调的,是其中拦截器部分的执行调用:

resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);  


表面上,它只是执行了拦截器中的intercept方法,如果我们结合拦截器来看,就能看出点端倪来:

public String intercept(ActionInvocation invocation) throws Exception {    
    String result = null;    
   
        before(invocation);    
        // 调用invocation的invoke()方法,在这里形成了递归调用    
        result = invocation.invoke();    
        after(invocation, result);    
   
        return result;    
}  


原来在intercept()方法又对ActionInvocation的invoke()方法进行递归调用,ActionInvocation循环嵌套在intercept()中,一直到语句result = invocation.invoke()执行结束。这样,Interceptor又会按照刚开始执行的逆向顺序依次执行结束。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics