前面一节描述的Struts2很多东西,这节是对源码进行分析描述,通过这一节应该对struts2有了清楚认识!

还是把Struts2这个框图贴出来:

第一步: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运行流程到此就算是结束了!

到此可能对于这个struts2框架大致运行架构清楚了!

转载于下面这个博客!

https://blog.csdn.net/u010890358/article/details/80245754

https://blog.csdn.net/q547550831/article/details/53267815------struts2系列讲的非常好

Struts2源码解析-----转载的更多相关文章

  1. underscore源码解析 (转载)

    转载出自http://www.cnblogs.com/human/p/3273616.html (function() { // 创建一个全局对象, 在浏览器中表示为window对象, 在Node.j ...

  2. Struts2源码解析2

    看了前面一节对Struts2各个模块运行有了大概了解,也对调用的函数有了一定的了解,本节希望打断点跑一个Struts2例子! 还是放在struts2结构图: 一:项目启动后解析web.xml文件,会解 ...

  3. jQuery整体架构源码解析(转载)

    jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...

  4. 转载:Bootstrap 源码解析

    Bootstrap 源码解析 前言 Bootstrap 是个CSS库,简单,高效.很多都可以忘记了再去网站查.但是有一些核心的东西需要弄懂.个人认为弄懂了这些应该就算是会了.源码看一波. 栅格系统 所 ...

  5. 【转载】Xutils3源码解析

    Github源码地址:https://github.com/wyouflf/xUtils3 原文地址 :http://www.codekk.com/blogs/detail/54cfab086c476 ...

  6. 【转载】okhttp源码解析

    转自:http://www.open-open.com/lib/view/open1472216742720.html https://blog.piasy.com/2016/07/11/Unders ...

  7. 【转载】FloatingActionButton源码解析

    原文地址:https://github.com/Rowandjj/my_awesome_blog/blob/master/fab_anlysis/README.md loatingActionButt ...

  8. 【转载】Scroller源码解析

    原文地址:https://github.com/Skykai521/AndroidSdkSourceAnalysis/blob/master/article/Scroller%E6%BA%90%E7% ...

  9. 【Caffe】源码解析----caffe.proto (转载)

    分析caffe源码,看首先看caffe.proto,是明智的选择.好吧,我不是创造者,只是搬运工. 原文地址:http://blog.csdn.net/qq_16055159/article/deta ...

随机推荐

  1. windows 查看端口占用、关闭端口

    cmd打卡命令窗口 1)netstat -an 查看所有活动连接 2)netstat -aon| findstr “xxxx” 找到指定端口的连接 3)taskkill  /F /PID xxxx 终 ...

  2. Centos7上安装java

    1.默认情况下,系统安装的有jdk1.8,但是使用javac测试时会不识别这个命令,   意味着,java还是未安装好. 2.把java升级即可,此时java已经可用. yum -y install ...

  3. Linux查看版本(centos)

    1.查看内核版本 1.1.uname -a 1.2.cat /proc/version 2.查看发行版本 cat /etc/redhat-release

  4. 把JavaScript对象转化成JSON对象

    js => jsonvar jsonVar = {key: value}var jsonString = JSON.stringify(jsonVar)  //将JS对象转换为JSON字符串va ...

  5. fedora 26 安装 mplayer smplayer

    dnf install mplayer dnf install smplayer 提示仓库 里没有这个软件 fedora默认不提供一些有版权争议的软件,非开源的项目包,所以需要用rpm fusion源 ...

  6. 十进制 -> 十六进制

    x /16 依次取余 ,最先余作十六进制的最低 字节有效位,最后的余数  作最高的字节有效位,其中我们需要注意理解 的是  一个 数据的 最高字节及  内存的 高地址及低地址 更进一步的就算机器存储的 ...

  7. java面试题复习(四)

    31.内部类可以引用它的外部类的私有成员吗? 可以,内部类对象可以访问创建它的外部类对象的成员 32.final关键字有哪些用法? 修饰类时该类不能被继承,修饰方法时,该方法不能被重写,修饰变量时表示 ...

  8. node-服务器

    原生: const http=require('http'); http.createServer((request,response)=>{ response.writeHead(200,{& ...

  9. [Docker] 使用 Dockerfile 的多级构建 (multi-stage builds)

      Multi-stage build 即在一个 Dockerfile 中使用多个 FROM 指令.   每个 FROM 指令可以使用不同的基础镜像,并且每一个都开启新的构建阶段.   你可以有选择地 ...

  10. Oracle 正则

    https://www.cnblogs.com/qmfsun/p/4467904.html 匹配汉字可以用Oracle 内置函数 unistr('\4e00') -unistr('\9fa5') 来定 ...