struts2工作原理

strut2工作原理:
/**servlet Filters**/
1.首先用户通过web中的HttpServletRequest的一条标准的过滤链 向servelet容器发送请求

2.过滤器链包括可选的 ActionContextCleanUp 过滤器,用于系统整合技术

3.过滤完了之后,接着调用 FilterDispatcher,FilterDispatcher 查找  ActionMapper,以确定这个请求是否需要调用某个 Action。

/**Struts Core**/
4.ActionMapper 确定需要调用某个 Action,FilterDispatcher 将控制权交给 ActionProxy。

5.ActionProxy 依照框架的配置文件(struts.xml),通过(Configuration Manager即配置文件管理器)找到需要调用的 Action 类。

6.Action 调用效应返回结果,ActionInvocation 根据 struts.xml 配置文件,查找对应的转发路径(即是通过Result找到转发路径),最后通过HttpServletResponse把响应转发给view层展示。

7.最后效应过滤器链(ActionContextCleanUp 过滤器),清理线程的局部ActionContext,FilterDispatcher不会清理ActionContext。反之,FilterDispatcher会清除所有线程的局部变量。

strut2中几个重要变量的关键类的工作原理:
一.FilterDispatcher类工作流程
1.init 方法:初始化过滤器,创建默认的 dispatcher 对象并且设置静态资源的包。

2.destory 方法:核心业务是调用 dispatcher.cleanup() 方法。cleanup 释放所有绑定到 dispatcher 实例的资源,包括销毁所有的拦截器实例。

3.doFilter 方法:(1)首先过滤器尝试把 request 匹配到一个 Action mapping(),如果匹配,Action 处理被委托给 dispatcher 的 serviceAction 方法,否则,doFilter 将会通过 dispatcher 创建一个错误页;
(2)如果请求的是静态资源。资源被直接拷贝到 response 对象,同时设置对应的头信息。
(3)如果请求无处理直接通过过滤器,访问过滤器链的下个资源。

二.doFilter()方法中的valueStack (重点)
1.valueStack 的建立是在 doFilter 的开始部分,在 Action 处理之前。即使访问静态资源 ValueStack 依然会建立,保存在 request 作用域。

2.ValueStack 在逻辑上包含 2 个部分:object stack 和 context map,object stack 包含 Action 与 Action 相关的对象。context map 包含各种映射关系。request,session,application,attr,parameters 都保存在 context map 里。
解释名词(1)atrr: 依次搜索 page, request, session, 最后 application 作用域。

3.准备和包装 request,包含 2 步:
(1)准备请求,设置区域和字符编码 包装 request,如果包含文件上传,则网页表单设置为 multipart/form-data,返回 MultiPartRequestWrapper 类型。
(2)如果普通表单提交,返回 StrutsRequestWrapper。这个类是 multipart/form-data 的父类。

4.ActionMapping 代表 struts.xml 文件中的一个 Action 配置,被传入到 serviceAction 中。注意 ActionMapping 不代表 Action 集合,只代表某个对应的 Action。

5.如果是一个 Action 请求,( 请求路径在 struts.xml 有对应的 Action 配置 ),则调用 dispatcher.serviceAction() 处理。

6.finally 语句块中调用 ActionContextCleanUp.cleanUp(req),以清除 ActionContext。

三.serviceAction()方法的工作原理:
1.获取和创建Valuestack(Valuestack 对象保存在 request 里,对应的 key 是ServletActionContext.STRUTS_VALUESTACK_KEY。调用代理之前首先创建 Valuestack 副本,调用代理时使用副本,调用后使用原实例恢复。本处的值栈指 object stack。)

2.获取配置文件中 <action/> 配置的字符串,创建一个 Action 代理对象(ActionProxy)。调用代理并把处理委托给代理对象的 execute 方法。

3.处理结束后,恢复值栈的代理调用前状态,如果 action 或者 result 没有找到就报错

四.cleanup()方法
1.销毁 ObjectFactory
(ObjectFactory 对象工厂,用来创建核心的框架对象)

2.销毁本线程的Dispatcher 实例,销毁 DispatcherListeners
(DispatcherListeners 为监听器设计模式,仅仅在 Dispatcher 的 init 和 destory 中执行)

3.调用每个拦截器的 destroy() 方法,销毁每个拦截器;销毁 action context
(actionContext 从根本上讲是一个容器,action 执行所需要的对象,如会话,请求参数,区域信息,valueStack,action等,包含在其中)

4.销毁 xwork 配置对象(configuration)


Struts2
1. 什么是ValueStack
每个Action类的对象实例会拥有一个ValueStack对象,用于将用户请求参数值赋给Action中的对应属性
Struts2接收到一个.action的请求后,并不会调用Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点,并赋予默认值
Struts 2调用拦截器链中的拦截器,根据用户请求参数值去更新ValueStack对象顶层节点的相应属性的值
最后将ValueStack对象中的属性值,赋给Action类的相应属性,并调用Action类的Action方法
ValueStack会在请求开始时被创建,请求结束时消亡
为什么要用ValueStack
  在Struts1中,Action为了能将处理的结果传递给下一个页面进行显示,通常需要借助于request对象
而Struts2会自动的将ValueStack与Action中的属性关联,基于这一点,可在Action中定义某个属性,转发到JSP页面后,直接从ValueStack中取出数据并显示
可直接使用EL来访问ValueStack中数据
  页面用valueStack用法:   
         ValueStack vs=(ValueStack)request.getAttribute("struts.valueStack");
      //调用ValueStack的findValue方法获取Action中的shops属性值
     String[] shops=(String[])vs.findValue("shops");
ActionSupport类是一个工具类,实现了Action和Validateable接口,提供了数据校验功能

3.原来在intercept()方法又对ActionInvocation的invoke()方法进行递归调用,ActionInvocation循环嵌套在intercept()中,一直到语句result = invocation.invoke()执行结束。这样,Interceptor又会按照刚开始执行的逆向顺序依次执行结束。一个有序链表,通过递归调用,变成了一个堆栈执行过程,将一段有序执行的代码变成了2段执行顺序完全相反的代码过程,从而巧妙地实现了AOP。这也就成为了Struts2的Action层的AOP基础。


拦截器和过滤器之间有很多相同之处,但是两者之间存在根本的差别。其主要区别为以下几点:
1)拦截器是基于JAVA反射机制的,而过滤器是基于函数回调的。
2)过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容器
3)拦截器只能对Action请求起作用,而过滤器可以对几乎所有的请求起作用。
4)拦截器可以访问Action上下文、值栈里的对象,而过滤器不能
5)在Action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

上述是我自己总结的,如果还是不能够理解的话,可以参考以下网址:
http://my.oschina.net/yangphere/blog/42035

你可能感兴趣的:(struts)