structs2 运行流程分析

来源:互联网 发布:淘宝卖家给买家发短信 编辑:程序博客网 时间:2024/05/17 04:07

相关的API:

ActionMapping:Simple class that holds the action mapping information used to invoke a Struts action. The name and namespace are required


ActionMapper:When given an HttpServletRequest, the ActionMapper may return null if no action invocation request matches, or it may return an ActionMapping that describes an action invocation for the framework to try


ActionProxy:ActionProxy is an extra layer between XWork and the action so that different proxies are possible. 


ActionInvocation:An ActionInvocation represents the execution state of an Action. It holds the Interceptors and the Action instance. By repeated re-entrant execution of the invoke() method, initially by the ActionProxy, then by the Interceptors, the Interceptors are all executed, and then the Action and the Result.

运行流程:

1. 请求发送给 StrutsPrepareAndExecuteFilter


2. StrutsPrepareAndExecuteFilter 询问 ActionMapper: 该请求是否是一个 Struts2 请求(即是否返回一个非空的 ActionMapping 对象)


3. 若 ActionMapper 认为该请求是一个 Struts2 请求,则 StrutsPrepareAndExecuteFilter 把请求的处理交给 ActionProxy


4. ActionProxy 通过 Configuration Manager 询问框架的配置文件,确定需要调用的 Action 类及 Action 方法


5. ActionProxy 创建一个 ActionInvocation 的实例,并进行初始化


6. ActionInvocation 实例在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。


7. Action 执行完毕,ActionInvocation 负责根据 struts.xml 中的配置找到对应的返回结果。调用结果的 execute 方法,渲染结果。在渲染的过程中可以使用Struts2 框架中的标签。


8. 执行各个拦截器 invocation.invoke() 之后的代码


9. 把结果发送到客户端


——————————第二次编辑——————————————————


作者:郭无心
链接:https://www.zhihu.com/question/22027032/answer/74516331
来源:知乎

可以参看一个模拟struts2实现拦截器的例子:
//
Main文件(直接调用ActionInovocation的invoke方法进行循环执行interceptor)
public class Main {public static void main(String[] args) {new ActionInvocation().invoke();}}


ActionInvocation文件(循环调用各interceptor的intercept方法,结束则调用action的execute方法)

import java.util.ArrayList;import java.util.List;public class ActionInvocation {List<Interceptor> interceptors = new ArrayList<Interceptor>();int index = -1;Action a = new Action();public ActionInvocation() {this.interceptors.add(new FirstInterceptor());this.interceptors.add(new SecondInterceptor());}public void invoke() {index ++;if(index >= this.interceptors.size()) {a.execute();}else { this.interceptors.get(index).intercept(this);}}}
FirstInterceptor文件(intercept方法重新调用ActionInvocation的invoke方法达到循环的效果)

public class FirstInterceptor implements Interceptor {    public void intercept(ActionInvocation invocation){System.out.println(1);invocation.invoke();System.out.println(-1);    }}
//SecondInterceptor文件public class SecondInterceptor implements Interceptor {    public void intercept(ActionInvocation invocation) {                System.out.println(2);invocation.invoke();System.out.println(-2);}}


//Interceptor接口(intercept方法参数为ActionInvocation)public interface Interceptor {    public void intercept(ActionInvocation invocation);}//Action类(action类,执行)public class Action {public void execute() {System.out.println("execute!");}}


1)拦截器(Interceptor)是Struts2的核心组成部分,是XWork体系的重要组件。
2)Struts2很多功能都是构建在拦截器基础之上的,例如文件的上传下载、国际化、数据类型转换和数据校验等等。
3)Struts2拦截器在访问某个Action方法之前和之后实施拦截
4)Struts2拦截器是可插拔的,拦截器是AOP(面向切面编程)的一种实现。
5)拦截器栈(Interceptor Stack):将拦截器按一定的顺序联结成一条链,在访问被拦截的方法时,Struts2拦截器链中的拦截器就会按其之前定义的顺序依次调用。


&amp;lt;img src=&quot;https://pic1.zhimg.com/04ef3abf5fa3ffeff6b8783c30b0597c_b.png&quot; data-rawwidth=&quot;305&quot; data-rawheight=&quot;301&quot; class=&quot;content_image&quot; width=&quot;305&quot;&amp;gt;类似于FilterChain,但又有很大的不同,比如FilterChain需要在编写doFilter方法时自行实现返回时的过滤以及链的向下执行,并且是在Servlet容器执行的这些操作。类似于FilterChain,但又有很大的不同,比如FilterChain需要在编写doFilter方法时自行实现返回时的过滤以及链的向下执行,并且是在Servlet容器执行的这些操作。
相反Intercetor是通过反射,通过XWork容器调用,自动返回拦截。

每个拦截器都是实现了com.opensynphony.xwork2.interceptor.Interceptor接口的Java类
public interface Interceptor extends Serializable{       void destroy();       void init();       String intercept(ActionInvocation invaocation) throws Exception;}
---init : 该方法将在拦截器被创建后立即被调用,它在拦截器的生命周期内只被调用一次,可以在该方法中对相关资源进行必要的初始化。---interecept : 每拦截一个请求该方法就会被调用一次。---destroy: 该方法将在拦截器被销毁之前被调用它在拦截器的生命周期内也只被调用一次。
这三个方法在Servlet和Filter当中都有这样的类似定义,显然这个拦截器也是单例模式的。

Struts2会依次调用为某个Action而注册的每一个拦截器的interecept方法。
每次调用interecept方法时,Struts2会传递一个ActionInvocation接口的实例。

ActionInvocation: 代表一个给定 Action 的执行状态, 拦截器可以从该类的对象里获得与该 Action 相关联的 Action 对象和 Result 对象. 在完成拦截器自己的任务之后, 拦截器将调用 ActionInvocation 对象的 invoke 方法前进到 Action 处理流程的下一个环节.
AbstractInterceptor 类实现了 Interceptor 接口. 并为 init, destroy 提供了一个空白的实现

---------------------------------
自定义拦截器的步骤
1)定义一个拦截器的类
> 可以实现Interceptor接口
> 继承AbstractInterceptor抽象类
2)在struts.xml 当中进行配置
例如我们的例子
<package name="default" namespace="/" extends="struts-default">   <interceptors>      <interceptor name="hello"                 class="com.struts2.interceptors.MyInterceptor">      </interceptor>      <interceptor-stack name="atguigustack"> <interceptor-ref name="defaultStack">   <param name="fileUpload.maximumSize">2097152</param>   <!--             <param name="fileUpload.allowedTypes">text/html,text/xml</param>   <param name="fileUpload.allowedExtensions">html,dtd,xml</param>   -->           </interceptor-ref></interceptor-stack>   </interceptors>   <default-interceptor-ref name="atguigustack">   </default-interceptor-ref>   <action name="testUpload" class="com.struts2.upload.app.UploadAction"><result>/success.jsp</result><result name="input">/upload.jsp</result>   </action>  <action name="testDownload"class="com.struts2.download.app.DownLoadAction"><result type="stream"><param name="bufferSize">2048</param></result>   </action><action name="testToken" class="com.struts2.token.app.TokenAction">   <interceptor-ref name="hello"></interceptor-ref><interceptor-ref name="tokenSession"></interceptor-ref><interceptor-ref name="defaultStack"></interceptor-ref><result>/success.jsp</result><result name="invalid.token">/token-error.jsp</result></action> </package>



------------------------------
一图胜千言(感觉跟Servlet标准中的FilterChain模式实现不会有太多区别)&amp;lt;img src=&quot;https://pic2.zhimg.com/2ddff64c87f67c630f4265cac1777719_b.png&quot; data-rawwidth=&quot;960&quot; data-rawheight=&quot;720&quot; class=&quot;origin_image zh-lightbox-thumb&quot; width=&quot;960&quot; data-original=&quot;https://pic2.zhimg.com/2ddff64c87f67c630f4265cac1777719_r.png&quot;&amp;gt;&amp;lt;img src=&quot;https://pic2.zhimg.com/0095fecf492250c5bbdbd347cd49e5cd_b.png&quot; data-rawwidth=&quot;679&quot; data-rawheight=&quot;540&quot; class=&quot;origin_image zh-lightbox-thumb&quot; width=&quot;679&quot; data-original=&quot;https://pic2.zhimg.com/0095fecf492250c5bbdbd347cd49e5cd_r.png&quot;&amp;gt;--------------------------------------------------------------------------------

0 0