首页 > 其他 > 详细

Struts2源码研究

时间:2016-03-17 02:19:38      阅读:150      评论:0      收藏:0      [点我收藏+]

一、Struts2容器初始化过程

?

1> 创建Dispatcher对象

? ? a> 将ServletContext设置到Dispatcher中

? ? b> 读取default.properties,struts-default.xml,struts-plugin.xml,struts.xml等配置文件

? ? c> 获取创建Container全局容器,在此期间会解析配置文件并创建xml文件中配置的Bean

? ? d> 使用ContainerHolder的静态方法将Container实例放入ThreadLocal中

? ? e> 初始化一些全局配置,比如是否为开发模式等

? ? f> 将Dispatcher对象放入Container全局容器中

2> 创建PrepareOperations和ExecuteOperations两个对象并将Dispatcher放入其中,之后doFilter会用到这两个对象

?

二、Struts2插件机制

?

介绍一下ObjectFactory类,它是创建对象的工厂,这些对象包括Action对象、结果类型、拦截器、验证器、类型转换器等。可以在struts.xml中配置

	<bean type="com.opensymphony.xwork2.ObjectFactory" name="smallbug" class="cn.smallbug.struts2.action.SmallbugFactory" />
	<constant name="struts.objectFactory" value="smallbug" />

?

SmallbugFactory是ObjectFactory的子类,以此来修改默认的对象工厂,spring插件也是配置这个参数达到了整合Struts2的目的。之所以可以这样做是因为在Struts2容器中很多地方都是调用了ObjectFactory的buildXxx方法来获取实例的。在运行时如果你给它配置了不同的子类,那么如何创建Action就有你来决定了。想使用某种工具直接可以将它的jar包放到部署目录下就ok,不想用直接取走,连配置文件都不用该极其灵活。这种灵活度的实现也得益于struts-default.xml,struts-plugin.xml,struts.xml配置文件的依次加载,出现重复的话后者覆盖前者。

?

三、Action核心流程(过滤器匹配成功时触发)

? ?

1> PrepareOperations对象设置结果集

2> PrepareOperations对象创建ActionContext

? ? a> Dispatcher获取ValueStackFactory的实例然后创建ValueStack

? ? b> 将request,request.getParameterMap(),session,servletContext分别封装成map

? ? c> 将上述所有Map放入一个大Map中以它们的名字作为key

? ? d> 获取ValueStack中名为context的Map,将上述大Map以putAll的方式添加进context中

? ? e> 创建一个ActionContext对象将ValueStack添加进去

3> 调用Dispatcher的静态setInstance方法,将Dispatcher实例放入ThreadLocal中

4> 将Request对象包装为StrutsRequestWrapper对象,其作用在于如果request域中找不到的属性会去stack中找

5> 根据request,response创建mapping映射对象

6> 使用ExecuteOperations执行目标方法

? ? a> 创建代理Action

? ? ? ? -> createAction(contextMap);创建Action:调用ObjectFactory中的buildAction方法创建action

? ? ? ? -> stack.push(action);把action放入到了栈顶

? ? ? ? -> 获取拦截器

? ? b> proxy.execute()执行代理方法,按照顺序的方式执行:

? ? ? ? -> 拦截器

? ? ? ? -> 执行action

? ? ? ? -> 执行结果集

? ? ? ? -> 如果拦截器的返回形式不是return invocation.invoke方法,则按照倒叙的方式执行

? ? c> 清空数据

?

四、拦截器调用原理

?

? ? ?首先是代理对象触发ActionInvocation实例的invoke方法,拦截器开始执行。ActionInvocation中有一个Iterator<InterceptorMapping>数据结构,保存着要依次执行的拦截器。看一下调用代码

?

 if (interceptors.hasNext()) {
                final InterceptorMapping interceptor = interceptors.next();
                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack.push(interceptorMsg);
                try {
                                resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
                            }
                finally {
                    UtilTimerStack.pop(interceptorMsg);
                }
            } else {
                resultCode = invokeActionOnly();
            }

?

它其实是把自己的实例作为参数传了下去,这时候拦截器链上的节点执行会有两种情况

? ? ?1> return invocation.invoke();它会在执行完自己的逻辑之后返回ActionInvocation之后不再执行。

?

? ? ?2> invocation.invoke();//之后还有逻辑,它会在执行完自己的逻辑之后返回ActionInvocation,在ActionInvocation的逻辑执行完之后还会执行自己剩余的部分的逻辑。

?

?

?

Struts2源码研究

原文:http://smallbug-vip.iteye.com/blog/2283668

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!