Struts2请求流程和原理(源码解析,运行流程)
发布日期:2021-07-30 03:26:27 浏览次数:2 分类:技术文章

本文共 2789 字,大约阅读时间需要 9 分钟。

      前言:此文章为本人复习Struts2的一个学习记录,如果有什么错误的地方可以留言讨论,当前Struts2更新到了2.5.16更新了不少东西,支持JSR303,debug标签只能在dev mode环境下面显示等等,看官们如果有需要可以移步下面链接因为本次测试不会涉及到这些: 。

      IDE: eclipse Neon ; Struts2 version : 2.3.16

    下面按照Eclipse Debug结合Struts2官方给出的流程图来进行一步步的解析,其中涉及到众多的类因此只会根据主流程来描述:

Struts2-Architecture.png

第一步:HttpServletRequest进入到StrutsPrepareAndExecuteFilter(图上ActionContextCleanUp这个类在集成SiteMesh才有用的其余时候可以不管)

       流程图上的FilterDispacther即在web.xml中配置的filter:StrutsPrepareAndExecuteFilter这个也是Struts2的核心(下面提到的该类指向这个类)在Struts项目中所有的请求都需要经过它的处理。(注意:更早的版本会有所不同)当每次启动服务器的时候第一次请求都会调用该类的init方法,随后的请求会调用doFilter。如图一我们直接把断点打在doFilter中开始调试。

图一:

         根据官方的流程图可以看到请求通过FilterDispacther后会进入到ActionMapper,ActionMapper这个类是一个接口就是用来匹配当前的请求是否有对应的action。它有4个实现类分别是:RestfulActionMapper,DefaultActionMapper(默认使用),CompositeActionMapper,PrefixBasedActionMapper。

         通过ActionMapper得到ActionMapping这个类(图二),ActionMapping对象是用来存放ActionMapper(默认DefaultActionMapper)解析后得到的name,nameSpace,method,extension,params,result 具体可以查看官方文档这边不再赘述。根据图三可以清楚的看到getMapping这个方法就是解析我们的请求来得到ActionMapping,值得一提的是在这个方法中最后调用到的方法parseActionName(图四)有个if判断条件为allowDynamicMethodCalls,这个值的意思就是说是否允许请求使用Struts DMI(动态方法调用例如访问的形式为test!test,意思就是访问test这个对应action中的test方法),Struts配置文件default.properties中默认设置为false,如果你要允许使用DMI就在struts.xml中添加<constant name="struts.enable.DynamicMethodInvocation" value="true"/>。最后通过这个方法后我们得到了ActionMapping。

图二:

图三:

图四:

第二步:StrutsPrepareAndExecuteFilter调用dispatcher类的serviceAction创建ActionProxy

         得到ActionMapping后接着执行execute.executeAction方法。此时StrutsPrepareAndExecuteFilter会调用dispatcher这个类的serviceAction(图六),这个方法会对valuStatck等进行处理,重要的是这边会根据ActionMapping这个对象中的属性(前文提到)以及configurationManager(加载Struts2的配置文件)来生成一个ActionProxy如果这个ActionProxy成功创建的话会执行execute方法(图七)反之如果匹配不到Action即无法生成相应的代理对象会返回404页面。

图五:

图六:

图七:

第三步:通过ActionProxy对象调用Actioninvocation的invoke方法执行所有的拦截器

      在ActionProxy的execute方法中最后执行的是Actioninvocation(创建ActionProxy过程中默认生成的是它的子类DefaultActionInvocation)的invoke方法。从图八中可以看到从Strtus2从这里开始对拦截器进行处理。这边的interceptors集合在初始化ActionProxy的时候通过配置文件(struts的Struts-default.xml中<interceptor-stack name="defaultStack">)得到。在执行图八中intercept方法时候Struts会把所有的拦截器执行一遍,接着执行请求所指的action中的方法并且按照后进先出的规则执行先前的拦截器(可查看官方流程图)。

      下面我们来分析下这个过程。首先通过interceptors.next()获取配置文件中的ExceptionMappingInterceptor对象(这个时候interceptors集合的指针下移也就是说下一次的interceptors.next()指向了AliasInterceptor对象)接着调用ExceptionMappingInterceptor的intercept方法并把当前的DefaultActionInvocation对象作为参数传递进去。而在intercept中又调用了DefaultActionInvocation的invoke方法(图九)接着在剩下的所有拦截器中重复调用Invoke方法直到把所有的拦截器调用完毕。

图八:

图九:

第四步:执行HttpServletRequest对应的Action方法并返回Result

         当到了最后一个拦截器DeprecationInterceptor(默认配置情况下最后一个)的时候,此时interceptors.HasNext()为false,因此执行invokeActionOnly方法(图八)。这个方法是用来执行ActionProxy代理的那个Action方法(本次事例为test!add因此对应的Action方法就是add)并获得Result的过程,该过程用了Java的反射机制来实现(图十)。最后按照后进先出的方式依次返回所有拦截器的值最终返回Result视图。

图十:

        至此整个Struts2运行流程到此就算是结束了,上述只是这个流程的主要一部分,其中还涉及到了许多的内容这边不再详细的去探讨。感谢阅读,希望读者能够看懂,有所疑问可以留言。

转载地址:https://blog.csdn.net/u010890358/article/details/80245754 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:解决 Eclipse Struts,Hibernate,Spring等配置文件没有提示
下一篇:SpringMVC整合Mybatis+Maven+Bootstrap的简单Demo

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年03月27日 09时56分07秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章