`
HJXia
  • 浏览: 88066 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Struts2源码分析讨论

阅读更多
最近一直在研究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这个集合才对.
大家可以讨论讨论,有知道的也可以告诉我.谢谢.
分享到:
评论
14 楼 gutou9 2008-11-27  
我的理解是这样的 :
1.
DefaultActionInvocation
interceptors.next()


然后
interceptor.getInterceptor().intercept(DefaultActionInvocation.this)


把程序调用转交给 Interceptor,

2.

Interceptor 逻辑执行完毕后,执行
 return invocation.invoke();


把程序调用还给 Interceptor,

步骤 1 2 反复执行,interceptors 集合 也就一路next下去,
直到 Interceptor 被遍历一遍。

这个用法好像叫 java 回调。


13 楼 水依月 2008-09-08  
楼主源代码可以共享下么?
12 楼 xxrrss 2008-08-22  
这个不是递归!而是一种设计模式!叫装饰模式!如果大家对Java中IO设计有比较深的理解的话,会发现很熟悉!
11 楼 huangxin_sy 2008-04-02  
请问XWORK2包中的源码在哪能找到啊?谢谢了
我的mail:huangxin_sy@163.com
10 楼 leisure 2008-03-31  
似乎可以搞个简单例子,模拟这个过程:
 
public interface Test {//类似Interceptor接口
      public String test(TestInvocation invocation);
  }
  public class Test1 implements Test {
      public String test(TestInvocation invocation) {
         System.out.println("hello!in test1");
         return invocation.invoke();
      }
  }
  public class Test2 implements Test {

      public String test(TestInvocation invocation) {
	 System.out.println("hello in test2");
          return invocation.invoke();
      }
  }
  public interface TestInvocation {//类似ActionInvocation
      public String invoke();
  }
  public class DefaultInvocation implements TestInvocation{
      public Iterator interceptors;
      public String result;
      public String invoke() {
	       if(interceptors.hasNext()){
		 Test test=(Test)interceptors.next();
		 result=test.test(this);
	       }
	       else
		 result= "end";
	       return result;
      }
      public void init(){
		Test t1=new Test1();
		Test t2=new Test2();
		List<Test> tlist=new ArrayList<Test>();
		tlist.add(t1);
		tlist.add(t2);
		interceptors=tlist.iterator();
	}
	public static void main(String[] args){
		DefaultInvocation inc=new DefaultInvocation();
		inc.init();
		inc.invoke();
	}
   }
9 楼 eric1028 2008-03-29  
另外想说的是,这里面的递归真是有点怪。呵呵。
这不是常见的那种递归,即一个方法递归调用自身。
而是,这个方法调用一个Interceptor的方法,并把自身传进去,让Interceptor调回自身这个方法,然后再以同样的方式去调用另一个Interceptor……这样子递归。

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

看清楚了这两点,上面的代码也就没什么了吧~^_^
8 楼 eric1028 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

7 楼 myoldman 2008-03-28  
hysoft 写道
DefaultActionInvocation 这个类我咋没找到呢??

这个类在xwork的源码中,需要去opensymphony网站上下载xwork的源码.
6 楼 hysoft 2008-03-28  
DefaultActionInvocation 这个类我咋没找到呢??
5 楼 myoldman 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中的代码和递归的调用模式就能很好的理解了.



4 楼 hsy537 2008-03-21  
能否整个流程给讲解一下
3 楼 huahun 2008-03-21  
你好,想请教下,怎么在自定义的拦截器中得请求参数的值呢?
2 楼 HJXia 2007-12-27  
恩,果然是这样.终于搞清楚了整个流程.较struts1而言,struts2的设计真是巧妙加精华.如果大家有什么关于struts2源码的问题,也可以发出来大家讨论.希望可以给大家帮助.
1 楼 seadragonnj 2007-12-26  
这个嘛,你在找个Interceptor看看,你会发现它调用了这个invoke(),这个好像叫递归吧,说错了当没说啊(偶水平也很差啊)

相关推荐

    struts2部分源码分析

    本篇文章将深入探讨Struts2的运行原理,通过源码分析来揭示其内部工作机制。 首先,我们从核心组件开始。Struts2的核心组件包括Action、FilterDispatcher、Interceptor和Result。Action是业务逻辑的载体,它接收...

    struts2框架源码

    了解这些基本概念后,深入源码分析可以发现以下关键技术点: 1. **Dispatcher Servlet**:Struts2的核心控制器,负责接收HTTP请求,通过ActionMapper找到对应的Action,然后调用ActionInvocation进行拦截器链的执行...

    struts2 源码

    源码分析是深入理解一个框架工作原理的关键步骤,对于提升开发技能和解决问题有着不可估量的价值。下面将详细讨论Struts2.1.8版本中的核心概念和关键组件。 1. **Action类与拦截器(Interceptor)**: Struts2的核心是...

    struts2深入详解源码1-5章

    本资料包包含的是《Struts2深入详解》一书的源码分析,涵盖了从第一章到第五章的内容,并附带了相关的jar包,方便读者结合理论与实践进行学习。 首先,让我们从第一章开始,Struts2的基础知识。这一章通常会介绍...

    xwork_struts2 源码

    3. **源码分析**:研究这两个jar的源码,可以深入理解Struts2的工作原理,包括: - **ActionInvocation**:它是Action执行过程的封装,负责调用Interceptor链并执行Action方法。 - **...

    struts2-src

    Struts2源码分析可以从以下几个关键点展开: 1. **Action与Dispatcher**:在Struts2中,Action类是业务逻辑处理的主要载体。用户请求首先会被Struts2的前端控制器(DispatcherServlet)捕获,然后根据配置文件...

    浪曦struts2源码第二课

    在“浪曦struts2源码第二课”中,我们将会深入探讨Struts2的核心概念、工作原理以及源码分析。 首先,让我们了解Struts2的基本架构。Struts2的核心组件包括Action、Result、Interceptor(拦截器)等。Action是业务...

    浪曦struts2源码第9课

    如果这节课涉及到更深入的源码分析,可能会讲解Struts2的请求处理流程、拦截器的实现原理、Action的生命周期,甚至包括如何调试和优化Struts2应用。对于Java Web开发者来说,掌握这些知识点对提升开发效率和解决实际...

    Struts 2权威指南源码

    本资源“Struts 2权威指南源码”包含了该框架的详细学习材料,总共21章,覆盖了从基础到高级的全方位内容。以下是对这些章节可能涵盖的知识点的详细解析: 1. **Struts 2概述**:介绍Struts 2的核心概念,发展历程...

    struts2_ppt

    关于源码方面,Struts2的源码分析有助于我们理解其内部工作原理。例如,它如何处理请求、如何执行拦截器链、以及如何进行结果映射。深入源码可以帮助开发者解决遇到的问题,或者定制自己的扩展功能。 工具方面,...

    struts2标签下的用户注册

    Struts2是一个强大的MVC(模型-视图-控制...通过实际操作,结合源码分析,可以加深对Struts2工作原理的理解,进一步提高开发效率。在实践中,还应注意安全问题,如密码加密存储、防止SQL注入等,以确保用户数据的安全。

    struts-2.0.14源码

    源码分析是理解其工作原理、进行自定义扩展或排查问题的关键。以下是关于Struts 2.0.14源码的一些核心知识点: 1. **MVC模式**:Struts 2遵循MVC架构,将应用程序分为模型、视图和控制器三个部分,有效地解耦了业务...

    Struts2权威指南源码第4章

    最后,结合源码分析,读者将有机会看到Struts2框架内部的工作流程,例如请求的流转过程、Action的调度以及拦截器的调用顺序。这有助于开发者更深入地理解框架,从而能够更好地优化和调试自己的应用。 总之,"Struts...

    struts2 权威指南pdf+源代码

    书中不仅涵盖了Struts2的基础知识,还详细讨论了如何将Struts2与其他流行技术如Spring和Hibernate进行整合,这对于理解Struts2在实际项目中的应用有着极大的帮助。 1. **核心概念:**Struts2的核心包括Action、...

    Struts-menu源码分析(转贴).rar

    在分析Struts-menu的源码时,我们可以深入理解Struts框架的工作原理、MVC模式的应用以及如何实现自定义标签库。下面将详细讨论相关知识点。 1. **Apache Struts框架**: Apache Struts是一个开源的Java EE Web应用...

    struts2实现的在线考试系统

    下面将详细讨论Struts2框架以及它在构建在线考试系统中的应用。 1. **Struts2框架**:Struts2是Apache软件基金会的一个开源项目,它是Struts1的升级版,具有更好的灵活性和扩展性。Struts2的核心是Action类,它处理...

    JSP+Struts2开发诚欣企业免费电子商城网站系统源代码

    我们将围绕其开发技术、功能模块以及源代码分析等方面展开讨论。 一、技术栈介绍 JSP(JavaServer Pages)是一种基于Java的动态网页技术,它允许开发者在HTML页面中嵌入Java代码,实现了视图与逻辑的分离。而...

    MyBatis+Spring+Struts2

    这个组合通常被称为SSH(Struts2、Spring、Hibernate)或者SSM(Spring、SpringMVC、MyBatis),但在这里我们讨论的是SSH版本。这个框架集合提供了强大的后端数据管理、服务层抽象以及用户界面控制。 【描述】虽然...

    Struts2+ajax注册验证源码

    Struts2和Ajax是两种在Web开发中广泛使用的技术,它们结合使用可以为用户带来更加流畅和实时的交互体验。在此项目中,"Struts2+ajax注册验证源码"是一个利用这两种技术实现的简单注册验证系统。接下来,我们将详细...

Global site tag (gtag.js) - Google Analytics