Struts2的运行流程及其工作原理

  • Struts2核心组件介绍

    ActionMapper:通过method参数将请求转发到具体的action

     

    ActionProxy代理:是Action的一个代理类,也就是说Action的调用是通过ActionProxy实现的,其实就是调用了ActionProxy.execute()方法,而该方法又调用了ActionInvocation.invoke()方法。归根到底,最后调用的是DefaultActionInvocation.invokeAction()方法。

    ActionInvocation:就是Action的调用者。ActionInvocation在Action的执行过程中,负责Interceptor、Action和Result等一系列元素的调度。

    Interceptor拦截器:是Struts 2的一个强有力的工具,有许多功能(feature)都是构建于它之上,如国际化、校验等。

  • 运行流程

1.当用户的发出请求,比如http:localhost:8080/Struts2/helloworld/helloworldAction.action,请求会被Tomcat接收到,Tomcat服务器来选择处理这个请求的Web应用,那就是由helloworld这个web工程来处理这个请求。

2.Web容器会去读取helloworld这个工程的web.xml,在web.xml中进行匹配,但发现,由struts2这个过滤器来进行处理(也就是

StrutsPrepareAndExecuteFilter),根据Filter的配置,找到FilterDispatcher(Struts2的调度中心)

3.然后会获取FilterDispatcher实例,然后回调doFilter方法,进行真正的处理

PS:FilterDispatcher是任何一个Struts2应用都需要配置的,通常情况下,web.xml文件中还有其他过滤器时,FilterDispatcher是放在滤器链的最后;如果在FilterDispatcher前出现了如SiteMesh这种特殊的过滤器,还必须在SiteMesh前引用Struts2的ActionContextCleanUp过滤器

 

对应Struts2的架构图如下

 

Struts2的运行流程及其工作原理

 

4.这时FilterDispatcher会将请求转发给ActionMapper。ActionMapper负责识别当前的请求是否需要Struts2做出处理。ActionMapper就类似于公司的保安,来识别是不是当前客户是不是我公司的人

 

对应Struts2的架构图如下

 

Struts2的运行流程及其工作原理

 

5.如果需要Struts2处理,ActionMapper会通知FilterDispatcher,需要处理这个请求,FilterDispatcher会停止过滤器链以后的部分,(这也就是为什么,FilterDispatcher应该出现在过滤器链的最后的原因)。然后建立一个ActionProxy实例,这个对象作为Action与xwork之间的中间层,会代理Action的运行过程。

 

对应Struts2的架构图如下

 

Struts2的运行流程及其工作原理

 

6.ActionProxy对象在被创建出来的时候,并不知道要运行哪个Action,它手里只有从FilterDispatcher中拿到的请求的URL。

而真正知道要运行哪个Action的是ConfigurationManager。因为只有它才能读取我们的strtus.xml

 

(在服务器启动的时候,ConfigurationManager就会把struts.xml中的所有信息读到内存里,并缓存,当ActionProxy带着URL向他询问要运行哪个Action的时候,就可以直接匹配、查找并回答了)

 

对应Struts2的架构图如下

 

Struts2的运行流程及其工作原理  -> Struts2的运行流程及其工作原理

 

7.ActionProxy知道自己该干什么事之后(运行哪个Action、相关的拦截器以及所有可能使用的result信息),然后马上建立ActionInvocation对象了,ActionInvocation对象描述了Action运行的整个过程。

注意:Action完整的调用过程都是由ActionInvocation对象负责

 

对应Struts2的架构图如下

 

Struts2的运行流程及其工作原理

 

 

8.在execute方法之前,好像URL请求中的参数已经赋值到了Action的属性上,这就是我们的"雷锋"—拦截器。

拦截器的运行被分成两部分,一部分在Action之前运行,一部分在Result之后运行,而且顺序是刚好反过来的。也就是在Action执行前的顺序,比如是拦截器1、拦截器2、拦截器3,那么运行Result之后,再次运行拦截器的时候,顺序就变成拦截器3、拦截器2、拦截器1了。

这就好比,你要去奶奶家,需要通过 水泊梁山->盘丝洞 -> 索马里,到了奶奶家,看奶奶回来的时候,就必须要通过 索马里 -> 盘丝洞 -> 水泊梁山。

所以ActionInvocation对象执行的时候需要通过很多复杂的过程,按照指定拦截器的顺序依次执行。

 

对应Struts2的架构图如下

 

Struts2的运行流程及其工作原理

 

 

9.到了奶奶家,然后执行Action的execute方法

 

 

Struts2的运行流程及其工作原理

 

10.然后根据execute方法返回的结果(Result),去struts.xml中匹配选择下一个页面

 

Struts2的运行流程及其工作原理

 

11.根据结果(Result)找到页面后,在页面上(有很多Struts2提供的模板),可以通过Struts2自带的标签库来访问需要的数据,并生成最终页面

注意:这时还没有给客户端应答,只是生成了页面

 

Struts2的运行流程及其工作原理

 

12.最后,ActionInvocation对象倒序执行拦截器,从奶奶家回来

 

Struts2的运行流程及其工作原理

 

13.ActionInvocation对象执行完毕后,已经得到响应对象(HttpServletResponse)了,最后按与过滤器(Filter)配置定义相反的顺序依次经过过滤器,向客户端展示出响应的结果

 

得到完整Struts2架构图

 

Struts2的运行流程及其工作原理