struts2--关于值栈的概念性问题

重要参考:http://www.cnblogs.com/ningvsban/p/3739622.html

http://www.cnblogs.com/ningvsban/p/3739682.html

结论:

1 狭义值栈

  通常指的是实现com.opensymphony.xwork2.util.ValueStack接口的对象,目前就是com.opensymphony.xwork2.ognl.OgnlValueStack对象。

  狭义值栈主要用来存取动态EL(表达式语言)运算需要的值和结果,当然OgnlValueStack对象主要是用来支持OGNL(对象图导航语言)运算的。狭义值栈里面存放着一些OGNL可以存取访问的数据,典型如:

  • Action的实例,这样就可以通过OGNL来访问Action实例中的属性的值了
  • OGNL表达式运算的值,可以设置到值栈中,可以主动访问值栈对象,强行设置
  • OGNL表达式产生的中间变量,比如在后面使用Struts2的标签的时候,使用循环标签,自然会有循环的变量,这些都存放在值栈中
2广义值栈

最大的值栈为广义值栈,通常指的是ActionContext对象,ActionContext是Action运行的上下文,每个ActionContext是一个基本的容器,包含着Action运行需要的数据,比如请求参数、会话等。

  ActionContext是线程安全的,每个线程有一个独立的ActionContext,这样你就不用担心值栈中值的线程安全问题了。ActionContext里面存放有很多的值,典型如:

  • Request的parameters:请求中的参数,要注意这里的数据是从请求对象里面拷贝出来的,因此这里数据的变化是不会影响到请求对象里面的参数的值的
  • Request的Attribute:请求中的属性,这里其实就是个Map,存放着请求对象的属性数据,这些数据和请求对象的Attribute是连动的
  • Session的Attribute:会话中的属性,这里其实就是个Map,存放着会话对象的属性数据,这些数据和会话对象的Attribute是连动的
  • Application的Attribute:应用中的属性,这里其实就是个Map,存放着应用对象的属性数据,这些数据和应用对象的Attribute是连动的
  • Value stack:也就是狭义值栈,ActionContext以value stack作为被OGNL访问的根,简单点说,OGNL在没有特别指明的情况下,访问的就是value stack里面的数据
  • attr:在所有的属性范围中获取值,依次搜索page、request、session和application。

  我们知道Xwork与Web是无关的,因此Action不用去依赖于任何Web容器,不用和Servlet 的API去交互,但是Action需要能访问到Web应用的数据,不仅仅是取得请求参数的值,往往也需要在Action里直接获取请求或会话的一些数据,对于这些数据,现在都可以通过ActionContext来获取到。

关于广义值栈和狭义值栈

你会看到,在ActionContext里面其实是包含着狭义值栈的,正是因为这个原因,再加上ActionContext还包含其他的数据,因此把ActionContext称为广义值栈。今后在说值栈的时候,没有特别指明的情况下,多数就是指的广义值栈,反正开发的时候都是说从值栈中获取值。当然,有一种情况除外,就是在页面上使用OGNL的时候,没有特殊标识的情况下,默认是从value statck中取值的。

值栈其实就是内存分析,在Struts2中就叫根对象和栈文本,类似于JAVA中对变量和对象的内存分析


值栈ValueStack是Struts2框架核心组件,它提供对上下文信息和执行环境中元
素的访问机制。其在底层实现了一个栈
值栈由以下4个层级对象组成
(1)临时对象:这些对象在请求处理过程中需要临时保存,比如集合中当前正在迭代的元素;
(2)
(2) 模型对象:当Action实现了ModelDriven接口时,模型对象就会被存放在栈中被执行的Action前面;否则不存在这个级别的内容。
(3) Action对象:此对象为当前正在执行的action。
(4) 命名对象:任何对象都可以被赋予一个标志符而成为命名对象。比如与HTTP同等作用域的对象集合对应的Struts2命名对象,#application、#session、#request、#attr和#parameters等。

当struts2框架接收到一个HTTP请求时,它立刻创建一个ActionContext、ValueStack、Action对象 , 然后把action对象存放进ValueStack 中,再通过ActionContext 对象访问ValueStack 中的信息,而这个访问的过程就是OGNL表达式访问操作

值栈中分为root根对象和栈文本,值栈中主要存放Action对象,栈文本里主要是一些Map映射parameters、request、session、application、attr

Ø在action中访问值栈
每个请求都建立一个与相应Action对应的ActionContext作为OGNL的上下文环境和ValueStack,并且把Action里面的属性值压入ValueStack,这时的属性值都是初始化值
从ActionContext 中获取上下文对象
ActionContext actionContext=ActionContext.getContext();
再从上下文对象中获取值栈
ValueStack valueStack=actionContext.getValueStack();

Ø操作根对象中的数据
从值栈中获取指定位置的根对象
valueStack.getRoot().get(0);
这个对象可以是当前的action对象,然后就可以操作当前对象中的数据了
它还提供了更加方便的取值方法,直接就从根对象中取值
valueStack.findValue(“…");
给根对象中的属性设置值,如果属性名称一样,会覆盖之前的属性值
valueStack.setValue(“…");//要求action中有set方法,即给属性重新赋值
valueStack.set(“…”);//随意一个属性名称,在根对象中会生成一个HashMap,(在后台调试中可以看到),不需要set方法,就是一个独立的属性(最新版本一样)
还可以往值栈中压对象,把对象压力栈顶
valueStack.getRoot().push(“…");

Ø操作栈文本中的数据
因为栈文本中主要存放parameters、request、session、application、attr的Map映射,以便在页面上直接可以访问。其实这个栈文本就是为了封装servlet中的request、session等对象,实现松耦合,以后对request等对象的参数或属性的操作就可以用requestMap的属性操作
获取requestMap
requestMap=(Map)ActionContext.getContext().get("request");
然后通过requestMap的key(参数或者属性) requestMap.get(“key”),就能获取参数或者属性的值了
因为当一个请求过来,ActionContext就能接受所有的请求参数,并且存放在ActionContext 栈文本中,可以获取对应的栈文本或者对其进行修改
给requestMap赋值,其实底层就是在给request对象赋值
(Map)ActionContext.getContext().get("request"). put(“”,””);

Ø在页面中访问值栈
在Struts2页面中操作值栈,OGNL表达式需要配合Struts标签才可以使用
如:<s:property value="name"/>
为了方便在页面端测试,打开<s:debug></s:debug>标签

一个OGNL表达式,必须选择ActionContext中的一个对象作为根对象(root),默认情况下,是选择valueStack作为根对象,如果需要使用另外5个对象作为根对象,需要加上#前缀 

简练总结:

广义值栈包括临时变量、狭义值栈(value stack,默认狭义value stack为根对象,是一个意思,尤其在OGNL表达式中),还有application session request attr parameters(都在栈文本中) 这三类,重要的是在狭义值栈中,也就是默认的根对象中(可以指定栈文本为根对象),这里主要存放着action对象,以及action对象的一些属性变量(可以直接通过狭义值栈跳过根目录直接对根目录中的变量取值)

获得上下文对象(广义值栈)

ActionContext.getContext();

获得狭义值栈的方法

ActionContext.getContext().getValueStack();

获得狭义值栈中的根对象的方法(默认狭义值栈中的为根对象)
ActionContext.getContext().getValueStack().getRoot();
获取指定位置的根对象
ActionContext.getContext().getValueStack().getRoot().get(0);
直接通过狭义值栈跳过根目录直接对根目录中的变量取值
ActionContext.getContext().getValueStack().findValue(“…");
给根对象中的属性设置值,如果属性名称一样,会覆盖之前的属性值
valueStack.setValue(“…");//要求action中有set方法,即给属性重新赋值
valueStack.set(“…”);//随意一个属性名称,在根对象中会生成一个HashMap,(在后台调试中可以看到),不需要set方法,就是一个独立的属性(最新版本一样)
还可以往值栈中压对象,把对象压力栈顶
valueStack.getRoot().push(“…");

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章