1. struts2介绍

为什么要使用struts2而不是servlet

  1. 屏蔽http请求方式和具体业务之间的转化问题:struts2替代servlet的javabean就屏蔽了servlet里http的请求方式和具体业务动作转化的问题,javabean里的每一个方法都可以和每一个url请求一一对应,这必然减轻了开发的难度问题。
  2. 屏蔽异构数据导致的http请求差异:struts2通过配置文件的形式屏蔽了异构数据导致的http请求之间的差异,提供了统一化的管理,降低了开发难度,增加了程序健壮性。
  3. 统一的自定义标签更好的联合了control和view的关系
  4. 比过滤器更加先进的拦截器(采用反射技术),带来对请求更加强大的控制

2. struts2基本结构

2.1 key

  1. Servlet Filters(servlet就包含了过滤器的概念了): 多个过滤器组成的过滤器链,客户端的所有请求都要经过Filter链的处理
  2. Struts Core: 核心部分
  3. Interceptors: Struts2提供了很多默认的拦截器,可以完成日常开发的绝大部分工作;而我们自定义的拦截器,用来实现实际的客户业务需要的功能。
  4. User Created: 由开发人员创建的,包括struts.xml、Action、Template,这些是每个使用Struts2来进行开发的人员都必须会的。

2.2 struts2组件简析

  1. FilterDispatcher: 是整个Struts2的调度中心,也就是MVC中的C(控制中心),根据ActionMapper的结果来决定是否处理请求,如果ActionMapper指出该URL应该被Struts2处理,那么它将会执行Action处理,并停止过滤器链上还没有执行的过滤器。
  2. ActionMapper:会判断这个请求是否应该被Struts2处理,如果需要Struts2处理。
  3. ActionProxy :它会创建一个 ActionInvocation实例, 位于Action和xwork之间,使得我们在将来有机会引入更多的实现方式,比如通过WebService来实现等。
  4. ConfigurationManager: 是xwork配置的管理中心,可以把它看做struts.xml这个配置文件在内存中的对应。
  5. struts.xml:是开发人员必须光顾的地方。是Stuts2的应用配置文件,负责诸如URL与Action之间映射关系的配置、以及执行后页面跳转的Result配置等。
  6. ActionInvocation :真正调用并执行Action,它拥有一个Action实例和这个Action所依赖的拦截器实例。ActionInvocation会按照指定的顺序去执行这些拦截器、Action以及相应的Result。
  7. Interceptor(拦截器):是Struts2的基石,类似于JavaWeb的Filter,拦截器是一些无状态的类,拦截器可以自动拦截Action,它们给开发者提供了在Action运行之前或Result运行之后来执行一些功能代码的机会。
  8. Action: 用来处理请求,封装数据。

3. 运行流程

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过滤器

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

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

  1. ActionProxy对象在被创建出来的时候,并不知道要运行哪个Action,它手里只有从FilterDispatcher中拿到的请求的URL。而真正知道 要运行哪个Action的是 ConfigurationManager。因为只有它才能读取我们的strtus.xml
    (在服务器启动的时候,ConfigurationManager就会把struts.xml中的所有信息读到内存里,并缓存,当ActionProxy带着URL向他询问要运行哪个Action的时候,就可以直接匹配、查找并回答了)

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

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

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

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

所以ActionInvocation对象执行的时候需要通过很多复杂的过程,按照指定拦截器的顺序依次执行。
9.到了奶奶家, 然后执行Action的execute方法

  1. 然后根据execute方法返回的结果(Result),去struts.xml中匹配选择下一个页面 11.根据结果(Result)找到页面后,在页面上(有很多Struts2提供的模板),可以通过Struts2自带的标签库来访问需要的数据,并生成最终页面 12.最后,ActionInvocation对象倒序执行拦截器,从奶奶家回来 13.ActionInvocation对象执行完毕后,已经得到响应对象( HttpServletResponse )了,最后按与过滤器(Filter)配置定义相反的顺序依次经过过滤器,向客户端展示出响应的结果

一句话总结
HttpServletRequest->过滤器->struts2框架验证接收处理->匹配struts.xml->确定某action处理->经过拦截器->处理->经过拦截器->HttpServletResponse

参考资料:
http://blog.csdn.net/watering_sea/article/details/47682729?utm_source=tuicool
http://www.tuicool.com/articles/RB3YBzN