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 ...
随机推荐
- IOS关于不同字体和不同颜色的选择
在项目中,用到一个功能,就是不同文字和不同颜色字体选择, 界面如下:,效果如下: 这个功能主要用到了textview的几个代理办法,其中一个重要的问题就是,在英文下和英文下的不同判断方式,以及是否有追 ...
- scp 从远程拷贝文件不需要密码
执行这一句,弹出来要你输入密码,输入一次后,以后再 scp 远程机的文件 再也不需要密码了 ssh-copy-id myusername@8.8.8.8
- 一个.net程序员的安卓之旅-Eclipse设置代码智能提示功能
一个.net程序员的安卓之旅-代码智能提示功能 过完年回来就决心开始学安卓开发,就网上买了个内存条加在笔记本上(因为笔记本原来2G内存太卡了,装了vs2010.SQL Server 2008.orac ...
- LINQ使用细节之.AsEnumerable()和.ToList()的区别
先看看下面的代码,用了 .AsEnumerable(): 1 var query = (from a in db.Table2 where a = SomeCondition3 select a.So ...
- 更改MyEclipse 之 jsp、js、java、xml文件字体大小设置
1.打开eclipse->window-->prefercess--->general--->appearance-->color and font ----> B ...
- 【转】Android各大发布市场
前言 如果只有一个或者少许的两三个Android市场,本文也没用存在的必要性,本文谨献给同在Android奋战的同仁. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnbl ...
- python利用redis构成一个队列
例子在 http://peter-hoffmann.com/2012/python-simple-queue-redis-queue.html 英文 http://www.django-china.c ...
- HTML5 Web app开发工具Kendo UI Web中如何绑定网格到远程数据
在前面的文章中对于Kendo UI中的Grid控件的一些基础的配置和使用做了一些介绍,本文来看看如何将Kendo UI 中的Grid网格控件绑定到远程数据. 众所周知Grid网格控件是用户界面的一个重 ...
- angularJS和jQuery的区别
问题: 假如我熟悉利用jQuery去开发客户端应用,那么我怎么上手angularjs,能否描述下所需要的模式转变,下面这些问题能够帮助你给出一个回答: 1.在设计客户端web应用的时候有什么区别,最大 ...
- angularJS——模块
一.在讲angularjs的模块之前,我们先介绍一下angular的一些知识点: AngularJS是纯客户端技术,完全用Javascript编写的.它使用的是网页开发的常规技术(HTML,CSS,J ...