StrutsPrepareAndExecuteFilter 【http://www.tuicool.com/articles/NVNbYn

struts2 和 struts1 的一个重要区别就是它进行了 Action 类和 Servlet 的解耦。

又提供了获取 Servlet API 的其它通道,就是 ActionContext (还有个 ServletActionContext ,其实 ServletActionContext 只是 ActionContext 的一个子类而已)。源码为证:public class ServletActionContext extends ActionContext implements StrutsStatics。

ActionContext 是 Action 执行时的上下文,可以看作是一个容器,并且这个容器只是一个 Map。

在ActionContext容器中存放的是 Action 在执行时需要用到的 VALUE_STACK 、 ACTION_NAME 、 SESSION 、 APPLICATION 、 ACTION_INVOCATION 等等对象,还可以存放自定义的一些对象。

在一个请求的处理过程拦截器、 action 类和 result 中任何时候获取的 ActionContext 都是跟当前请求绑定那一个。

首先是 ActionContext 类的源码:

public class ActionContext implements Serializable{

static ThreadLocal actionContext = new ThreadLocal();

public static final String ACTION_NAME = "com.opensymphony.xwork2.ActionContext.name";

public static final String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";

public static final String SESSION = "com.opensymphony.xwork2.ActionContext.session";

public static final String APPLICATION = "com.opensymphony.xwork2.ActionContext.application";

public static final String PARAMETERS = "com.opensymphony.xwork2.ActionContext.parameters";

public static final String LOCALE = "com.opensymphony.xwork2.ActionContext.locale";

public static final String TYPE_CONVERTER = "com.opensymphony.xwork2.ActionContext.typeConverter";

public static final String ACTION_INVOCATION = "com.opensymphony.xwork2.ActionContext.actionInvocation";

public static final String CONVERSION_ERRORS = "com.opensymphony.xwork2.ActionContext.conversionErrors";

public static final String CONTAINER = "com.opensymphony.xwork2.ActionContext.container";

Map<String, Object> context;

public ActionContext(Map<String, Object> context)

{

this.context = context;

}

//... ...

public static void setContext(ActionContext context)

{

actionContext.set(context);

}

public static ActionContext getContext()

{

return (ActionContext)actionContext.get();

}

public void setContextMap(Map<String, Object> contextMap)

{

getContext().context = contextMap;

}

public Map<String, Object> getContextMap()

{

return this.context;

}

//... ...

public void setSession(Map<String, Object> session)

{

put("com.opensymphony.xwork2.ActionContext.session", session);

}

public Map<String, Object> getSession()

{

return (Map)get("com.opensymphony.xwork2.ActionContext.session");

}

//... ...

public Object get(String key)

{

return this.context.get(key);

}

public void put(String key, Object value)

{

this.context.put(key, value);

}

}

源码清晰的说明了我们编程中再熟悉不过的一行代码: ActionContext ctx = ActionContext.getContext();,原来我们所取得的ctx来自于 ThreadLocal 啊!熟悉 ThreadLocal 的朋友都知道它是与当前线程绑定的,而且是我们Java中处理多线程问题的一种重要方式。我们再看,类中有个 Map 类型的变量 context ,其实,它才是前面我们提到的真正意义上的容器,用来存放 Action 在执行时所需要的那些数据

到这里,他最初的那个问题已经很了然了。但是,他紧接着又一个疑惑提出来了:“那既然每个请求处理线程都有自己的 ActionContext ,那里面的那些数据是什么时候放进去的呢”?

这次我给他的建议是,动脑筋,用源码验证。既然 ActionContext 存放有 HttpServletRequest 及其中的参数,既然 ActionContext 贯穿于整个请求处理过程,那就从struts2请求处理的入口(过滤器 StrutsPrepareAndExecuteFilter )找,源码:

public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter

{

// ... ...

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)

throws IOException, ServletException

{

HttpServletRequest request = (HttpServletRequest)req;

HttpServletResponse response = (HttpServletResponse)res;

try

{

this.prepare.setEncodingAndLocale(request, response);

this.prepare.createActionContext(request, response);//就是在这里进行创建并初始化ActionContext实例

this.prepare.assignDispatcherToThread();

if ((this.excludedPatterns != null) && (this.prepare.isUrlExcluded(request, this.excludedPatterns))) {

chain.doFilter(request, response);

} else {

request = this.prepare.wrapRequest(request);

ActionMapping mapping = this.prepare.findActionMapping(request, response, true);

if (mapping == null) {

boolean handled = this.execute.executeStaticResourceRequest(request, response);

if (!handled)

chain.doFilter(request, response);

}

else {

this.execute.executeAction(request, response, mapping);

}

}

} finally {

this.prepare.cleanupRequest(request);

}

}

//... ...

}

再找到 prepare 对应的类 PrepareOperations ,查看方法 createActionContext () ,就一目了然了。

对于 ServletActionContext 作为 ActionContext 一个直接子类,原理也是类似的,感兴趣的朋友可以看一下。

ActionContext实现原理的更多相关文章

  1. 菜鸟学Struts2——Struts工作原理

    在完成Struts2的HelloWorld后,对Struts2的工作原理进行学习.Struts2框架可以按照模块来划分为Servlet Filters,Struts核心模块,拦截器和用户实现部分,其中 ...

  2. Web APi之过滤器执行过程原理解析【二】(十一)

    前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...

  3. Web APi之过滤器创建过程原理解析【一】(十)

    前言 Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把[筛子],那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从 ...

  4. [转] valuestack,stackContext,ActionContext.之间的关系

    三者之间的关系如下图所示: ActionContext  一次Action调用都会创建一个ActionContext  调用:ActionContext context = ActionContext ...

  5. Struts2(二):工作原理

    struts可查看源码:https://github.com/apache/struts 在学习struts2之前,我先看了一些比较早版本对struts2的工作原理相关的介绍,顺便抄写过来,用来帮助自 ...

  6. 深入研究Struts2(一)---Struts2是什么?它的工作原理是什么?

    本文绝对原创, 欢迎转载, 但是转载请记得注明文章出处:http://blog.csdn.net/izard999/article/details/39891281 近4年都在从事Android方 面 ...

  7. valuestack,stackContext,ActionContext.之间的关系

    者之间的关系如下图所示: relation ActionContext 一次Action调用都会创建一个ActionContext 调用:ActionContext context = ActionC ...

  8. 剖析SSH核心原理(一)

      在我前面的文章中,也试图总结过SSH,见 http://blog.csdn.net/shan9liang/article/details/8803989 ,随着知识的积累,总感觉以前说得比较笼统, ...

  9. strut2的原理

    Struts2 在项目中用到的核心是拦截器interceptor,OGNL(Object Graph navigation Language)对象图导航语言(用来操作ValueStack里面的数据), ...

随机推荐

  1. coursera 《现代操作系统》 -- 第十三周 期末考试

    一些概念在书上不好找,可以通过谷歌搜索,比如搜索中断向量, site:coursera.org 中断向量   3  下列关于中断和异常的叙述中,哪一个是错误的? x86系列处理器提供的4个处理器特权级 ...

  2. 【转】PowerVM 的主要组成部分及概念

    PowerVM 是在基于 IBM POWER 处理器的硬件平台上提供的具有行业领先水平的虚拟化技术家族.它是 IBM Power System 虚拟化技术全新和统一的品牌(逻辑分区,微分区,Hyper ...

  3. 阿里巴巴java开发手册阅读笔记

    1. long 或者 Long 初始赋值时,必须使用大写的 L. Long a = 2L; 2. POJO 类(DO/DTO/BO/VO )必须写 toString 方法 3. final 可提高程序 ...

  4. QThread与多线程(比较清楚)

    QThread类为我们提供了一种平台无关的管理线程的方式.一个QThread对象管理应用程序中的一个线程,该线程从run()函数开始执行.并且,默认情况下,我们可以在run()函数中通过调用QThre ...

  5. Android 屏幕适配扫盲、教程

    转载请注明出处:http://blog.csdn.net/my_truelove/article/details/66584865 訪问 ruicb.com,一键抵达我的博客! 扫描左側或右下方二维码 ...

  6. Linux服务管理(开启关闭防火墙)

    1.firewalld的基本使用 启动: systemctl start firewalld 关闭: systemctl stop firewalld 查看状态: systemctl status f ...

  7. su: warning: cannot change directory to : Permission denied ;-bash: bash_profile: Permission denied

    一.查看主目录权限对不对 1:问题描述 [root@ser6-52 ~]# su - mongodb su: warning: cannot change directory to /home/mon ...

  8. 虚拟化qemu-img的简单用法。

    qemu-img 命​令​行​工​具​是​ Xen 和​ KVM 用​来​格​式​化​各​种​文​件​系​统​的​,可​使​用​ qemu-img 格​式​化​虚​拟​客​户​端​映​像​.​附​加​ ...

  9. Win10在右键菜单添加“在此处打开命令窗口”设置项

    Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Directory\shell\OpenCmdHere] @="在此处打开命令 ...

  10. 一个用 C# 实现操作 XML 文件的公共类代码

    using System; using System.IO; using System.Data; using System.Xml; using System.Xml.XPath; namespac ...