struts2值栈内部数据结构详解
值栈是struts2内部一片很重要的区域,我在初学的时候,发现对于值栈这个数据结构的理解不是很深刻.例如OGNLContext是什么,ActionContext和值栈有什么关系.为什么ActionContext可以获得值栈和contextMap等等,这些都是在我初学的时候的难以理解的概念性问题.我在网上查找了很多资料,发现网上对于这一概念的解释很多都是复制粘贴或者解释的不是很清楚,因此写一篇博文帮助和我一样对于struts2值栈内部的数据结构的引用不清楚的童鞋!首先看看值栈的数据结构:
可以看出OgnlValueStack(值栈的实现类)包含两大部分:CompoundRoot(这其实是一个ArrayList.)和context.(我们通常称为contextMap).有了这个知识储备,接下来我们去看struts2关于值栈创建的源码:
在学习中,我们知道.值栈是和ActionContext同步创建的.因此需要了解值栈的创建,必须要进入ActionContext的创建方法里去观察.实际上,在struts2的核心过滤器StrutsPrepareAndExecuteFilter里在每次请求都会调用的doFilter方法里很容易就能找到这个方法.
进入到这个方法的内部观察,我们可以获得很多的信息.
整个过程分为4步,首先我们进入第一步(标注为1的代码)的方法内部,观察值栈的创建.
可以看出在struts2中值栈的实现类是OgnlValueStack.继续进入构造方法内部观察:
可以看出contextMap内部是维护了值栈的引用的.进入createDefaultContext方法内部:
从标志的这一句可以看出来contextMap内部也维护了root的引用.至此,我们知道,在这时,值栈已经创建完毕.且值栈的contextMap内部维护了值栈本身(OgnlValueStack)以及根(ComponentRoot)的引用.实际上,也可以看出来值栈的contextMap的实际数据结构为OgnlContext.接下来我们跟踪在PreparedOperations类内部createActionContext方法的stack.getContext().putAll这一句(上面标注的第二步).直接进入dispatcher.createContextMap的内部.
可以看出这个操作,就是在contextMap内部加入了各个域对象(request,ServletContext,session)的引用.通过contextMap可以获取到各个域对象的引用.
返回,在createActionContext方法内,继续往下走,第三步,可以看出将值栈(OgnlValueStack)的contextMap作为ActionContext的构造方法的参数传了进去.进入ActionContext类,实际上其内部是维护了一个叫做context的map来指向OgnlValueStack的contextMap的.而构造方法,正是对这个叫做context的成员变量初始化赋值.
实际上,ActionContext获取值栈.获取contextMap.获取Servlet相关的API都是通过这个context来实现的:
返回createActionContext方法,进入第四步.也就是ActionContext.setContext()方法.这个方法将新建的ActionContext以静态方法的参数传入ActionContext.进入这个方法内部:
原来这个方法是将新创建的ActionContext绑定到了ThreadLocal上.ThreadLocal的set方法是将ThreadLocal对象和数据对象作为键值对存入线程对象内部的一个Map类型的数据结构里.因此,由于ActionContext被绑定在ThreadLocal对象上,所以ActionContext是线程安全的.
综上,这就是值栈的创建过程.可以看出ActionContext和值栈同时创建,而且都是一次请求创建一次.生命周期为1次请求!值栈包括两部分:contextMap和root.其中contextMap维护了值栈本身和root的引用.ActionContext内部维护了contextMap的引用,因此一些教程上说的,ActionContext内部维护了值栈的引用是不正确的!正确的说法应该是ActionContext内部维护了contextMap的引用,contextMap内部维护了值栈的引用!为了便于理解,我画出了下面的图,仅供参考:
struts2值栈内部数据结构详解的更多相关文章
- [转]Redis内部数据结构详解-sds
本文是<Redis内部数据结构详解>系列的第二篇,讲述Redis中使用最多的一个基础数据结构:sds. 不管在哪门编程语言当中,字符串都几乎是使用最多的数据结构.sds正是在Redis中被 ...
- 探索Redis设计与实现6:Redis内部数据结构详解——skiplist
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- 探索Redis设计与实现7:Redis内部数据结构详解——intset
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- 探索Redis设计与实现5:Redis内部数据结构详解——quicklist
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- 探索Redis设计与实现4:Redis内部数据结构详解——ziplist
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- 探索Redis设计与实现3:Redis内部数据结构详解——sds
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- 探索Redis设计与实现2:Redis内部数据结构详解——dict
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- 【转】Redis内部数据结构详解——ziplist
本文是<Redis内部数据结构详解>系列的第四篇.在本文中,我们首先介绍一个新的Redis内部数据结构--ziplist,然后在文章后半部分我们会讨论一下在robj, dict和zipli ...
- 【转】Redis内部数据结构详解 -- skiplist
本文是<Redis内部数据结构详解>系列的第六篇.在本文中,我们围绕一个Redis的内部数据结构--skiplist展开讨论. Redis里面使用skiplist是为了实现sorted s ...
随机推荐
- 今天学了递归,感觉好复杂啊/(ㄒoㄒ)/~~
honio塔思路: 第一步 把A上的n-1个圆盘借助C移到B上: 第二步 把A上的一个圆盘移到C上: 第三步 把B上的n-1个圆盘借助A移到C上. 这显然符合递归的两个条件: ①具备边界条件:只有1个 ...
- 最新IP地址数据库 二分逼近&二分查找 高效解析800万大数据之区域分布
最新IP地址数据库 来自 qqzeng.com 利用二分逼近法(bisection method) ,每秒300多万, 比较高效! 原来的顺序查找算法 效率比较低 readonly string i ...
- mysql5.6.23免安装配置
1.官网下载,并解压 2.环境变量,path下,追加mysql的bin路径D:\Program Files\mysql\bin; 3.mysql目录下的my-default.ini重命名为my.ini ...
- sqlserver 插入数据时异常,仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'XXXXX.dbo.XXXXXXXXX'中的标识列指定显式值。
INSERT INTO XXXXXXXXX.dbo.XXXXXXXXX select * from XXXXXXXXX 仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'X ...
- MySQL免安装的配置
①:下载并获取解压路径: ②:修改 my-default.ini: ③:管理员身份进入cmd,并cd到上面的路径(否则发生错误2,找不到文件): ④:忘记ROOT密码如何重置:
- 二十五、JDK1.5新特性---枚举
与上篇文章介绍的相同,本文也是介绍jdk 1.5出现的新特性,本文将介绍枚举的相关用法. 在jdk 1.5 之前.Java可以有两种方式定义新类型:类和接口.对于大部分面向对象来说.这两种方法看起来似 ...
- javascript 创建 div
纯JAVASCRIPPT创建 (1):document.getElementById("要创建DIV位置的ID").innerHTML='<div>div里面的 ...
- 查询和删除表中重复数据sql语句
1.查询表中重复数据.select * from peoplewhere peopleId in (select peopleId from people group by ...
- 不可错过的炒鸡棒的js迷你库
小而美被实践是最好用的,这里收藏了一些很好用的js库,他们都功能单一且非常小. COOKIE.JS https://github.com/js-coder/cookie.js 如果你操作过cooki ...
- 点击区域外隐藏该区域,event.stopPropagation()
event.stopPropagation() Description: Prevents the event from bubbling up the DOM tree, preventing an ...