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 ...
随机推荐
- CMD命令大全
有关某个命令的详细信息,请键入 HELP 命令名 ASSOC 显示或修改文件扩展名关联. AT 计划在计算机上运行的命令和程序. ATTRIB 显示或更改文件属性. BREAK 设置或清除扩展式 CT ...
- 【Ngui 学习系列之一:简单组件的操作】
一.Buttonunity edit: Sprite作为父对象和背景 -- Collider -- Button script Label 作为子对象和显示文字代码: private UIButton ...
- 亲手使用Sencha Touch + phonepag开发Web APP随笔 -- 环境安装篇
最近因为有个项目需要制作APP,考虑到需要兼容Android和IOS,所以想采用WebAPP的方式来开发.现在是从零开始学习之路,走起- 通过网上博客和论坛,开始安装了一堆软件: 1. Sench ...
- SVN Client
https://ctf.open.collab.net/svn/repos/ankhsvn/trunk/src/ https://ctf.open.collab.net/svn/repos/sharp ...
- HTML入门教程
什么是 HTML? HTML(Hyper Text Markup Language)超文本标记语言,是用来描述网页的一种语言,不是一种编程语言,而是一种标记语言 (markup languag ...
- daterangepicker+ bootstrap +php +ajax +datatable双日历的使用
在练习基于bootstrap datatable的使用时,时间插件用到了daterangepicker,特做稍微了解,效果如图: 1.html <div class="panel& ...
- MVC系列2-Model
上一篇我讲了ASP.MET MVC的基础概念,我相信从上一篇,我们可以知道MVC的执行过程.这一篇我们开始讲解Model.我们知道,在我们的应用程序中,大多时候是在遵循业务逻辑通过UI操作数据.所以这 ...
- ftp协议详解
客户端与服务器之间,需要多条连接才能完成应用的协议,属于复杂协议.如FTP,PPTP,H.323和SIP均属于复杂协议. 这里主要介绍ftp协议的工作原理.首先,ftp通信协议有两种工作模式,被动模式 ...
- C# Socket编程笔记
1.按惯例先来介绍下socket Windows中的很多东西都是从Unix领域借鉴过来的,Socket也是一样.在Unix中,socket代表了一种文件描述符(在Unix中一切都是以文件为单 ...
- linux解压/压缩文件
1.*.tar 用 tar –xvf 解压 2.*.gz 用 gzip -d或者gunzip 解压 3.*.tar.gz和*.tgz 用 tar –xzf 解压 4.*.bz2 用 bzip2 ...