论坛首页 Java企业应用论坛

Struts2源码分析讨论

浏览 15657 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-12-26  
最近一直在研究struts2,看了李刚写的一本struts2权威指南,但感觉讲的还是有点浅,但是做为入门的话,还是不错的.现在开始看struts2的源码,但由于本人能力有限,看的是头晕脑涨的,有很多不明白的地方,所以想把不明白的地方贴出来跟大家一起讨论讨论.
其中有一处也觉的是比较关键的一步:
以下是DefaultActionInvocation中的invoke()方法的源码:

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 {
				    			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) {
    			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
    			if (proxy.getExecuteResult()) {
    				executeResult();
    			}

    			executed = true;
    		}

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

不明白是怎样迭代执行一个又一个的Interceptor中的intercept方法.
按照我的理解,至少我可以看到一个循环遍厉interceptors这个集合才对.
大家可以讨论讨论,有知道的也可以告诉我.谢谢.
   发表时间:2007-12-26  
这个嘛,你在找个Interceptor看看,你会发现它调用了这个invoke(),这个好像叫递归吧,说错了当没说啊(偶水平也很差啊)
0 请登录后投票
   发表时间:2007-12-27  
恩,果然是这样.终于搞清楚了整个流程.较struts1而言,struts2的设计真是巧妙加精华.如果大家有什么关于struts2源码的问题,也可以发出来大家讨论.希望可以给大家帮助.
0 请登录后投票
   发表时间:2008-03-21  
你好,想请教下,怎么在自定义的拦截器中得请求参数的值呢?
0 请登录后投票
   发表时间:2008-03-21  
能否整个流程给讲解一下
0 请登录后投票
   发表时间:2008-03-28  
从代码上看感觉有点象是回调加上递归具体分析如下
DefaultActionInvocation.invoke方法
    		if (interceptors.hasNext()) {
    			final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
    			UtilTimerStack.profile("interceptor: "+interceptor.getName(), 
    					new UtilTimerStack.ProfilingBlock<String>() {
							public String doProfiling() throws Exception {
				    			resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
				    			return null;
							}
    			});
    		} else {
    			resultCode = invokeActionOnly();
    		}

  • 判断interceptors这个Iterator中是否还有拦截器没有调用.
  • 如果有则调用Interceptor.intercept(DefaultActionInvocation.this),请注意这里把DefaultActionInvocation对象本身传入了拦截器,以便于拦截器执行处理后继续调用DefaultActionInvocation.invoke方法执行拦截器链.
  • 最后如果拦截器链中的拦截器都执行完毕,就直接调用invokeActionOnly(),该方法的处理就确定所需要调用的aciton的方法名,并且进行调用.

相应的interceptor中的处理如下
public String intercept(ActionInvocation invocation) throws Exception
{
   //aciton方法执行前拦截器的处理的代码
   //调用下一个拦截器或者action的execute方法.
   invocation.invoke();
   //action的execute方法调用完毕,并且执行完了preresultlistener和result.
   //action方法执行后的拦截器处理的代码
   return result;
}

由于该调用方法是类似递归方式的调用所以代码块执行顺序如struts文档中的描述.
假设有如下拦截器栈
<interceptor-stack name="xaStack">
  <interceptor-ref name="thisWillRunFirstInterceptor"/>
  <interceptor-ref name="thisWillRunNextInterceptor"/>
  <interceptor-ref name="followedByThisInterceptor"/>
  <interceptor-ref name="thisWillRunLastInterceptor"/>
</interceptor-stack>

那么执行的顺序如下
thisWillRunFirstInterceptor
  thisWillRunNextInterceptor
    followedByThisInterceptor
      thisWillRunLastInterceptor
        MyAction1
        MyAction2 (chain)
        MyPreResultListener
        MyResult (result)
      thisWillRunLastInterceptor
    followedByThisInterceptor
  thisWillRunNextInterceptor
thisWillRunFirstInterceptor

以上描述结合interceptor中的代码和递归的调用模式就能很好的理解了.



1 请登录后投票
   发表时间:2008-03-28  
DefaultActionInvocation 这个类我咋没找到呢??
0 请登录后投票
   发表时间:2008-03-28  
hysoft 写道
DefaultActionInvocation 这个类我咋没找到呢??

这个类在xwork的源码中,需要去opensymphony网站上下载xwork的源码.
0 请登录后投票
   发表时间:2008-03-29  
myoldman,你下面这段好像说错了:
thisWillRunFirstInterceptor
  thisWillRunNextInterceptor
    followedByThisInterceptor
      thisWillRunLastInterceptor
        MyAction1
        MyAction2 (chain)
        MyPreResultListener
        MyResult (result)
      thisWillRunLastInterceptor
    followedByThisInterceptor
  thisWillRunNextInterceptor
thisWillRunFirstInterceptor

因为MyAction2是类型为chain的Result,即,它也是Result,所以所有的PreResultListener应该在MyAction2之前被执行,然后MyAction2作为另外一个Action Invoke周期被执行。
我认为过程如下:
thisWillRunFirstInterceptor
  thisWillRunNextInterceptor
    followedByThisInterceptor
      thisWillRunLastInterceptor
        MyAction1
        MyPreResultListener
        thisWillRunFirstInterceptor
          thisWillRunNextInterceptor
            followedByThisInterceptor
              thisWillRunLastInterceptor
                MyAction2 (chain)
                MyPreResultListener
                MyResult (result)
              thisWillRunLastInterceptor
            followedByThisInterceptor
          thisWillRunNextInterceptor
        thisWillRunFirstInterceptor
      thisWillRunLastInterceptor
    followedByThisInterceptor
  thisWillRunNextInterceptor
thisWillRunFirstInterceptor

0 请登录后投票
   发表时间:2008-03-29  
另外想说的是,这里面的递归真是有点怪。呵呵。
这不是常见的那种递归,即一个方法递归调用自身。
而是,这个方法调用一个Interceptor的方法,并把自身传进去,让Interceptor调回自身这个方法,然后再以同样的方式去调用另一个Interceptor……这样子递归。

另外有一个要注意的是executed这个成员变量。
通常情况下,如果Action被正常执行,那么Action返回的Result会被执行,并把这个executed设为true。如果过程中出错,有异常抛出,那么可能在这之前就没有Result被执行,而ExceptionMappingInterceptor把异常映射到某个Result,然后返回来,这时,因为executed还是false,所以这个用于处理异常的Result会被执行。

看清楚了这两点,上面的代码也就没什么了吧~^_^
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics