zoukankan      html  css  js  c++  java
  • Struts2的执行流程(结合源码)

    本文适合学过和用过struts2的人。(转载:https://zhuanlan.zhihu.com/p/50245867)

    首先不多bb,上一张struts2的架构图,看着架构图对应着源码分析

     

    1、StrutsPrepareAndExecuteFilter: struts2的核心过滤器,作用:拦截请求。

    2、ActionMapper:核心过滤器会调用ActionMapper处理请求过来的url,看该请求是否需要

    struts2来进行处理,如果需要会返回一个ActionMapping对象里面包含了

    actionName,namespace等。

    3、ActionProxy: 可以把它当作一个老板,ActionInvocation当作它的秘书,它会调用

    ConfigurationManager去读取struts.xml的配置。

    4、ConfigurationManager: 读取struts.xml的配置,struts.xml在内存中的映射。

    5、struts.xml:这个就不用说了,是Stuts2的应用配置文件,负责诸如URL与Action之间映射关系

    的配置、以及执行后页面跳转的Result配置等。

    6、ActionInvocation: 作用是通过老板给的actionName,namespace等信息,调用对应的

    Action,当然执行之前先执行拦截器

    7、Interceptor: struts2的拦截器,默认20个,都是有着很重要的作用,比如参数拦截器(把

    请求过来的参数封装到对应的Action属性中),模型驱动拦截器(把请求参数封装成一个

    对象)。

    其他的就不介绍了,一看就懂

    首先先搭建好struts2的运行环境,引入jar包,配置核心拦截器,什么的就不说了。

    Action

    perfect.jsp(转发的页面)

    自定义拦截器

    一.

    首先在StrutsPrepareAndExecuteFilter中的doFilter方法中打个断点并访问action进入doFilter方法

    这里的代码就是判断该请求是否归struts2来处理,不归struts2管的话就直接doFilter放行,显然我们这里是需要struts2来处理的请求,所以进行下一步。

     

    二.

    程序执行到这一行看字面意思就知道是创建 数据中心,就是包含了很多数据的一个map,比如request,response,session等。这里我们进入这个方法看下到底做了什么

     

    三.

    这里我检几个重要的代码给大家看下,第一个圈出来的就是获取数据中心,第二个判断如果之前没有数据中心,我们就创建一个值栈ValueStack,学过struts2的就知道值栈中有个栈,还有个context(Map),接下来看它执行了什么呢,根据request,response创建一个contextMap,put给值栈中的Context,然后再把ValueStack中的Context的获取出来实例化ActionContext,也就是数据中心并返回。下面我们再回来继续走我们的核心过滤器

     

    四 .

    走到核心过滤器这里,我们看到了一个wrapRequest方法,就是包装request对象,学过struts2的就知道,在action中获得到的request就是被包装过的,可以看到没有执行这个方法之前这个request属于org.apache.catalina.connector这个包下。执行这个方法之后呢,竟然变成了org.apache.struts2.dispatcher.StrutsRequestWrapper类,那我们进入这个类中看到底包装了什么呢?

     

    五.

    看这个request中的包装类到底对什么进行了包装呢,发现里面的getAttribute方法有点猫腻,方法中先调用了父类的getAttribute方法,那我们看它父类到底是谁呢?

    就是原生的request对象,接着我们在看下面执行了什么。

    意思是如果ActionContext不为空且从原生request中获取到的值为null,我们就去值栈中获取值,调用findValue方法。再根据我们之前学的ognl表达式中,是不是通过一个类的属性就能去值栈中的栈中找到对应的值。由此我们可以推断出在request中取值,首先会在原生request

    中找,找不到再去值栈中找,现在值栈中的栈中找,再去Context域中找。

     

    六.

    接着我们再回来继续执行核心过滤器中的代码

    对应上面所说的会调用ActionMapper处理请求如果需要struts2处理这个请求就会返回一个mapping对象,不会就会放行,这里很明显mapping中封装了actionName和namespace等信息。

     

    七.

    接下来进入executeAction方法中看下。

    在进入serviceAction方法

    这里根据mapping中的信息创建老板对象,下面老板给mapping中的信息让ActionInvocation(秘书)去执行拦截器和action,我们进入execute方法。

     

    八.

    再进入秘书执行拦截器的方法

    判断这个是否还有拦截器,这里不用while循环而用了if,是因为把秘书对象传给拦截器中的intercept方法,方法中又递归调用了秘书的invoke方法,所以直到调用完拦截器才会执行Action。

    配置拦截器的时候,先配置了自定义的所以就执行了拦截器的前处理,然后放行,执行完系统的20个拦截器后,最终执行到Action中。

     

    九.

    最终返回结果跳转到视图,进行渲染,然后进行拦截器的后处理。

    为什么这样配置就会跳转到页面中呢,持续关注,下次分析源码解释。

  • 相关阅读:
    基于 VirtualApp 结合 whale hook框架实现hook第三方应用
    C/C++标准有哪些?
    【tips】编译epic异常解决
    Android 虚拟多开系列二——技术原理
    Android 虚拟多开系列一——技术调研
    Ubuntu 16.04 Apache2 更改访问html根路径方案(可解决403)
    android 原生 MediaPlayer 和 MediaCodec 的区别和联系(三)
    Android 原生 MediaPlayer 和 MediaCodec 的区别和联系(二)
    Android MediaPlayer 和 MediaCodec 的区别和联系(一)
    Mongodb实战使用指南
  • 原文地址:https://www.cnblogs.com/Cyfamoo/p/12883278.html
Copyright © 2011-2022 走看看