北京,雾霾天气阻止了今天的马拉松之行,蜗居一天。为一个问题“struts2如何保证ActionContext每次取的都是本次请求所对应的实例?”,给一个网友解释了半天。

首先,我们知道,struts2和struts1的一个重要区别就是它进行了Action类和Servlet的解耦。而又提供了获取Servlet API的其它通道,就是ActionContext(别跟我说还有个ServletActionContext,其实ServletActionContext只是ActionContext的一个子类而已)。源码为证:public class ServletActionContext extends ActionContext implements StrutsStatics

其次,他也知道,ActionContext是Action执行时的上下文,可以看作是一个容器,并且这个容器只是一个Map而已,在容器中存放的是Action在执行时需要用到的VALUE_STACK、ACTION_NAME、SESSION、APPLICATION、ACTION_INVOCATION等等对象,还可以存放自定义的一些对象。我想用过struts2的朋友们,大多也都知道这些吧。

第三,他奇怪的是,在一个请求的处理过程拦截器、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 context;

public ActionContext(Map 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 contextMap)

{

getContext().context = contextMap;

}

public Map getContextMap()

{

return this.context;

}

//... ...

public void setSession(Map session)

{

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

}

public Map 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一个直接子类,原理也是类似的,感兴趣的朋友可以看一下。

帮助别人,同时也是帮助自己。把这个处理的过程记录下来,希望对需要的朋友有所帮助。

java actioncontext_关于struts2中ActionContext的实现原理相关推荐

  1. Java并发编程包中atomic的实现原理

    转载自   Java并发编程包中atomic的实现原理 这是一篇来自粉丝的投稿,作者[林湾村龙猫]最近在阅读Java源码,这一篇是他关于并发包中atomic类的源码阅读的总结.Hollis做了一点点修 ...

  2. java零碎要点---struts2中redirect和redirectAction的区别

    struts2中redirect和redirectAction的区别 struts2中关于result的返回类型一般我们是转发到一个jsp页面或者是html页面等,但是struts2中的result的 ...

  3. Struts2中ActionContext和ServletActionContext

    转自:http://blog.sina.com.cn/s/blog_6c9bac050100y9iw.html 在Web应用程序开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在A ...

  4. Struts2中ActionContext介绍

    来源:http://blog.csdn.net/alex197963/article/details/2219912 在Web应用程序开发中,除了将请求参数自动设置到Action的字段中,我们往往也需 ...

  5. java 求正割_Java中AQS基本实现原理

    一.AQS概述 AQS全名AbstractQueuedSynchronizer,意为抽象队列同步器,JUC(java.util.concurrent包)下面的Lock和其他一些并发工具类都是基于它来实 ...

  6. java cas 实现_Java中CAS 基本实现原理

    一.前言 了解CAS,首先要清楚JUC,那么什么是JUC呢?JUC就是java.util.concurrent包的简称.它有核心就是CAS与AQS.CAS是java.util.concurrent.a ...

  7. struts2中 ServletActionContext与ActionContext区别

    1. ActionContext 在Struts2开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在Action里直接获取请求(Request)或会话(Session)的一些信息, ...

  8. 在Struts2中使用ValueStack、ActionContext、ServletContext、request、session等

    目录(?) [-] ValueStack 如何得到值栈: 如何将对象存入值栈: 让值栈执行表达式来获得值: 在JSP中跳过栈顶元素直接访问第二层: 在JSP中访问值栈对象本身(而不是它们的属性) Ac ...

  9. Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法...

    Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法 www.MyException.Cn   发布于:2012-09-15 ...

最新文章

  1. 高效排序算法(希尔排序)
  2. hadoop块的存储方式
  3. 《HBase企业应用开发实战》—— 2.5 停止HBase集群
  4. PHP语言Yii框架,Yii框架多语言站点配置方法分析【中文/英文切换站点】
  5. 基于Quartus II的在线调试方法
  6. 进程间通信 - 剪贴板实现
  7. crm系统是什么很棒ec实力_搭建CRM系统要明确几个步骤?什么样的CRM是真正有用的系统?...
  8. java 同步 异步 阻塞 非阻塞_Java日志正确使用姿势,大白话搞懂什么是同步/异步/阻塞/非阻塞...
  9. 100个模具设计常用基本知识,你懂得几个?设计师干货
  10. 酷我音乐android2.0,酷我音乐2012 2.0.0(For iphone)享受听歌“零“消费
  11. raid 物理盘缓存状态_查看RAID状态
  12. android怎么防8门神器,Android八门神器使用图文教程
  13. 传奇开服怎么开服?不会技术自己能开服吗?传奇开服需要准备什么?前期需要投入多少?
  14. 老师教我们用计算机画画就是彩虹,汉语拼音的教案
  15. CUPS学习二:CUPS概念介绍。
  16. iOS12-Swift5-Xcode10 Buildtime错误:/xx/Pods/Target Support Files/Pods-xx/Pods-xx.d
  17. AI智能语音客服机器人方案介绍/优点/核心
  18. python爬取pubmed的文献_爬虫获取pubmed中文献的标题和摘要
  19. 如何在 DAX 计算中隐藏未来日期?
  20. Odoo 8.0深入浅出开发教程(十) 附录

热门文章

  1. java criteria or_java – Criteria API组合AND / OR
  2. 开水果店需要准备什么,开水果店要准备什么
  3. android滑动卡片开源,CardSlideView 一行代码实现ViewPager卡片效果
  4. 关于Excel导出实例(适合新手,比较详细)
  5. 吃鸡提示找不到msvcp140.dll怎么办?绝地求生提示msvcp140.dll丢失解决方法
  6. 我和new bing的聊天记录
  7. live-server的使用
  8. nrf52832 - HID
  9. Android RIL 移植 SIM900
  10. [原]亲历水货笔记本电脑交易