???????????????????? 这篇文章大部分是转载的,虽然不知道作者是谁,但是还是非常膜拜的,描述的非常清晰,我觉得要是自己去陈诉也没有这么好,中间我修改了最新的核心控制器名称,主要是struts2的核心控制器现在并不是FilterDispatcher对象,而是StrutsPrepareAndExcuteFilter对象;中间有许多图片还是FilterDisptcher,我这边偷下懒,大家知道就行
?????
?
第一步 :我们先来看下struts2官方提供的运行流程图
?
?
????????????????????
这张图上分了好多块,彼此之间相互联系,先浏览一下各块的名字,再留心一下运行图最下面的图例,分为四种颜色。
?
第二部分我们粗略的陈诉下各个模块作用
??????????????????
?
第三部分接下来我们来真正陈诉下运行流程
???????????? 前提:我们正在模拟用户登入,进入index.jsp页面,该页面有两个输入框,分别是账号与密码,还有提交按钮,当输入的信息后然后提交到后台处理,插入web.xml文件中的过滤器配置
<!-- 配置Struts2控制器 --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping>
?
?
???????????? 过程:
?
1:首先是在登录页面,用户填入帐号和密码,然后点击提交按钮,好了,就从这里开始分析背后的处理流程,这是我们进行分析的起点。
2:当用户提交登录请求后,请求的URL为:“/helloworld /helloworldAction.action”,请求会被Tomcat服务器接收到,Tomcat服务器会根据请求URL中的web上下文,也就是?“/helloworld”,来选择处理这个请求的Web应用,那就是由helloworld这个web工程来处理这个请求。
3:Web容器会去读取helloworld这个工程的web.xml,在web.xml中进行匹配,发现后缀为“.action”的请求,由struts2这个过滤器来进行处理,根据Filter的配置,找到实际的类为FilterDispatcher。
4:Web容器会获取FilterDispatcher这个类的实例,然后回调doFilter方法,进行真正的处理。StrutsPrepareAndExcuteFilter作为前端控制器,是整个Struts2的调度中心。
注意:在架构图上,可以看到有三个过滤器层次,分别是ActionContextCleanUp、?SiteMesh等其他过滤器和FilterDispatcher。这三个层次中,ActionContextCleanUp和?FilterDispatcher是Struts2的过滤器,而SiteMeshSiteMesh等其他过滤器不是。
StrutsPrepareAndExcuteFilter是任何一个Struts2应用都需要配置的,一般出现在过滤器链的最后;如果在StrutsPrepareAndExcuteFilter前出现了如SiteMesh这种特殊的过滤器,还必须在SiteMesh前引用Struts2的ActionContextCleanUp过滤器。
在前面的helloworld中,并没有出现SiteMesh这种特殊的过滤器,所以只需要引用StrutsPrepareAndExcuteFilter就可以了。
这就相当于前进到Struts2架构图上的第一步,如下所示:
?
?
5:StrutsPrepareAndExcuteFilter将请求转发给ActionMapper。ActionMapper负责识别当前的请求是否需要Struts2做出处理。这就相当于前进到Struts2架构图上的第二步,如下所示:
?
6:ActionMapper告诉StrutsPrepareAndExcuteFilter,需要处理这个请求,StrutsPrepareAndExcuteFilter会停止过滤器链以后的部分,所以通常情况下:StrutsPrepareAndExcuteFilter应该出现在过滤器链的最后。然后建立一个ActionProxy对象,这个对象作为Action与xwork之间的中间层,会代理Action的运行过程。
这就相当于前进到Struts2架构图上的第三步,如下所示:
??????????????????
?
7:ActionProxy对象刚被创建出来的时候,并不知道要运行哪个Action,它手里只有从StrutsPrepareAndExcuteFilter中拿到的请求的URL。这时候,它去向ConfigurationManager询问到底要运行哪个Action。
回忆一下,某个特定的URL由哪个Action响应由谁负责,定义在什么地方呢?没错,在struts.xml里面。而?ConfigurationManager就是负责读取并管理struts.xml的,可以简单的理解为ConfigurationManager是?struts.xml在内存中的映像。
在服务器启动的时候,ConfigurationManager会一次性的把struts.xml中的所有信息读到内存里,并缓存起来,以保证ActionProxy拿着来访的URL向他询问要运行哪个Action的时候,就可以直接匹配、查找并回答了。
这就相当于前进到Struts2架构图上的第四步和第五步了,如下所示:
?
?
8:ActionProxy拿到了运行哪个Action、相关的拦截器以及所有可能使用的result信息,就可以着手建立ActionInvocation对象了,ActionInvocation对象描述了Action运行的整个过程。
注意:Action运行绝不仅仅只是运行Action的execute方法这么简单,还包括其他部分,完整的调用过程由ActionInvocation对象负责。
这就相当于前进到Struts2架构图上的第六步,如下所示:
?
9:回忆一下,HelloWorld中Action的execute方法运行的时候,是不是它的属性就已经有了请求中的参数呢?这说明,在execute方法之前,有人偷偷的帮我们做了这件事,把请求中的参数赋值到了Action的属性上,这个“有人”就是刚刚说的拦截器。
拦截器的运行被分成两部分,一部分在Action之前运行,一部分在Result之后运行,而且顺序是刚好反过来的。也就是在Action执行前的顺序,比如是拦截器1、拦截器2、拦截器3,那么运行Result之后,再次运行拦截器的时候,顺序就变成拦截器3、拦截器2、拦截器1了。
总之ActionInvocation对象执行的时候比较复杂,会做很多事:
这就相当于前进到Struts2架构图上的第七步,如下所示:
?
这就相当于前进到Struts2架构图上的第八步,如下所示:
?然后根据execute方法返回的结果,也就是Result,在struts.xml中匹配选择下一个页面,这就相当于前进到Struts2架构图上的第九步,如下所示:
?
这就相当于前进到Struts2架构图上的第十步,如下所示:
?
这就相当于前进到Struts2架构图上的第十一步,如下所示:
?
10:ActionInvocation对象执行完毕后,实际上就已经得到响应对象了,也就是HttpServletResponse对象,最后按与过滤器器配置定义相反的顺序依次经过过滤器,向用户展示出响应的结果。
这就相当于前进到Struts2架构图上的第十二步,得到最终完整的系统架构图了
?
?
?