虽然现在struts2已经慢慢淡出了视野,但是作为一个老框架,在我看来,学习价值还是有的,多阅读框架源码帮助很大,大家有空的话也可以尝试看看,好了,话不多说,今天的主题就像标题写的那样,主要探究struts2的执行流程,我们先来看一张图,相信对struts2稍有了解的读者都对这张图很熟悉了
这篇文章的重点就是围绕这张图,希望可以将整个流程说清楚,有不对的地方请大家指正~!!!
要看懂这张图,我们首先要对图中的一些对象有所了解,总结如下:
FilterDispatcher:整个Struts2的调度中心(现在用StrutsPrepareAndExecuteFilter),也就是MVC中的C(控制中心),根据ActionMapper的结果来决定是否处理请求,如果ActionMapper指出该URL应该被Struts2处理,那么它将会执行Action处理,并停止过滤器链上还没有执行的过滤器.
ActionMapper:会判断这个请求是否应该被Struts2处理,如果需要Struts2处理,ActionMapper会返回一个对象来描述请求对应的ActionInvocation的信息.
ActionProxy:它会创建一个ActionInvocation代理实例,位于Action和xwork之间,使得我们在将来有机会引入更多的实现方式,比如通过WebService来实现等.
ConfigurationManager:是xwork配置的管理中心,通俗的讲,可以把它看做struts.xml这个配置文件在内存中的对应.
struts.xml是Stuts2的应用配置文件,负责诸如URL与Action之间映射的配置、以及执行后页面跳转的Result配置等.
ActionInvocation:真正调用并执行Action,它拥有一个Action实例和这个Action所依赖的拦截器实例.ActionInvocation会执行这些拦截器、Action以及相应的Result.类似于调度器.
Interceptor(拦截器):拦截器是一些无状态的类,拦截器可以自动拦截Action,它们给开发者提供了在Action运行之前或Result运行之后来执行一些功能代码的机会。类似于我们熟悉的javax.servlet.Filter.
Action:动作类是Struts2中的动作执行单元。用来处理用户请求,并封装业务所需要的数据.
Result:Result就是不同视图类型的抽象封装模型,不同的视图类型会对应不同的Result实现,Struts2中支持多种视图类型,比如Jsp,FreeMarker等.
Templates:各种视图类型的页面模板,比如JSP就是一种模板页面技术.
Tag Subsystem:Struts2的标签库,它抽象了三种不同的视图技术JSP、velocity、freemarker,可以在不同的视图技术中,几乎没有差别的使用这些标签.
在对这些对象有一些了解后,我们就可以说说这整个流程啦,总结如下:
- 用户发出请求
请求会被Tomcat接收到,Tomcat服务器来选择处理这个请求的Web应用,就是选择哪一个web工程来处理这个请求.
- web容器去读这个工程的web.xml
在web.xml中进行匹配,发现是由struts2的过滤FilterDispatcher(StrutsPrepareAndExecuteFilter)来处理,找到该过滤器的实例(初始化).
- 找到FilterDispatcher,回调doFilter()
通常情况下,web.xml文件中还有其他过滤器时,FilterDispatcher是放在滤器链的最后;如果在FilterDispatcher前出现了如SiteMesh这种特殊的过滤器,还必须在SiteMesh前引用Struts2的ActionContextCleanUp过滤器.
- FilterDispatcher将请求转发给ActionMapper
ActionMapper负责识别当前的请求是否需要Struts2做出处理.
- ActionMapper告诉FilterDispatcher,需要处理这个请求,建立ActionProxy
FilterDispatcher会停止过滤器链以后的部分,所以通常情况下:FilterDispatcher应该出现在过滤器链的最后。然后建立一个ActionProxy对象,这个对象作为Action与xwork之间的中间层,会代理Action的运行过程
- ActionProxy询问ConfigurationManager,读取Struts.xml
ActionProxy对象刚被创建出来的时候,并不知道要运行哪个Action,它手里只有从FilterDispatcher中拿到的请求的URL.这时候,它问ConfigurationManager问到底要运行哪个Action.
而ConfigurationManager就是负责读取并管理struts.xml的,可以简单的理解为ConfigurationManager是struts.xml在内存中的映像.
在服务器启动的时候,ConfigurationManager会一次性的把struts.xml中的所有信息读到内存里,并缓存起来,以保证ActionProxy拿着来访的URL向他询问要运行哪个Action的时候,就可以直接匹配、查找并回答了.
- ActionProxy建立ActionInvocation对象
ActionProxy拿到了运行哪个Action、相关的拦截器以及所有可能使用的result信息,就可以着手建立ActionInvocation对象了,ActionInvocation对象描述了Action运行的整个过程.
- 在execute()之前的拦截器
在execute()之前会执行很多默认的拦截器.拦截器的运行被分成两部分,一部分在Action之前运行,一部分在Result之后运行,而且顺序是刚好反过来的。也就是在Action执行前的顺序,比如是拦截器1、拦截器2、拦截器3,那么运行Result之后,再次运行拦截器的时候,顺序就变成拦截器3、拦截器2、拦截器1了。
- 执行execute()方法
- 根据execute方法返回的结果,也就是Result,在struts.xml中匹配选择下一个页面
- 找到模版页面,根据标签库生成最终页面
- 在execute()之后执行的拦截器,和8相反
- ActionInvocation对象执行完毕
这时候已经得到了HttpServletResponse对象了,按照配置定义相反的顺序再经过一次过滤器,向客户端展示结果.