码迷,mamicode.com
首页 > 其他好文 > 详细

OGNL valueStack StackContext(ActionContext)深入分析(转+个人理解)

时间:2015-09-09 01:01:25      阅读:567      评论:0      收藏:0      [点我收藏+]

标签:

//还会补充

首先要有一个意识 ,为什么要了解这个?:

struts2中的表单是怎么通过表达式(EL or OGNL)来传给Action 和 拿到Action的值的。

 

值栈(根)对象也可以直接使用EL表达式访问,比如这里可以直接通过${user.username}来获取username的值,我们知道el表达式只能访问四种scope范围内的对象,那为什么这里能访问到值栈对象呢?原因是struts2对HttpServletRequet进行了一次封装,封装的代码主要是重写了getAttribute方法,简述重写此方法的核心代码:首先在原始的HttpServletRequest对象中查找el表达式中的属性,如果找不到再通过ActionContext获取值栈对象,进而再从值栈对象中查找el表达式中要访问的属性。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

当Struts2接收到一个.action的请求后,会先建立Action类的对象实例,但并不会调用Action方法,而是

①先将Action类的相应属性放到ValueStack对象的顶层节点(ValueStack对象相当于一个栈)。只是所有的属性值都是默认的值,如String类型的属性值为null,int类型的属性值为0等。处理完上述工作后,

②Struts2就会调用拦截器链中的拦截器,当调用完所有的拦截器后,最后会调用Action类的Action方法,在调用Action方法之前,会将

③ValueStack对象顶层节点中的属性值赋给Action类中相应的属性,注意,在这里就给我们呆了很大的灵活性。也就是说,在Struts2调用拦截器的过程中,可以改变ValueStack对象中属性的值,当改变某个属性之后,Action类的相应属性值就会变成在拦截器中最后改变该属性的这个值。(通过setValue方法可以改变

1、值栈(ValueStack)
Struts2将OGNL上下文设置为Struts2中的ActionContext(内部使用的仍然是OgnlContext),并将值栈设为OGNL的根对象。valuestack是ONGL的跟对象
我们知道,OGNL上下文中的根对象(valuestack)可以直接访问,不需要使用任何特殊的“标记”,而引用上下文中的其他对象则需要使用“#”来标记。由于值栈是 上下文中的根对象,因此可以直接访问。那么对于值栈中的对象该如何访问呢?Struts2提供了一个特殊的OGNLPropertyAccessor,它 可以自动查找栈内的所有对象(从栈顶到栈底),直接找到一个具有你所查找的属性的对象。也就是说,对于值栈中的任何对象都可以直接访问,而不需要使用 “#”。
假设值栈中有两个对象:student和employee,两个对象都有name属性,student有学号属性number,而 employee有薪水属性salary。employee先入栈,student后入栈,位于栈顶,那么对于表达式name,访问的就是student 的name属性,因为student对象位于栈顶;表达式salary,访问的就是employee的salary属性。正如你所见,访问值栈中的对象属 性或方法,无须指明对象,也不用“#”,就好像值栈中的对象都是OGNL上下文中的根对象一样。这就是Struts2在OGNL基础上做出的改进。
2、[N]语法
如上所述,如果想要访问employee的name属性,应该如何写表达式呢?我们可以使用[N].xxx(N是从0开始的整数)这样的语法来指定从哪一个位置开始向下查找对象的属性,表达式[1].name访问的就是employee对象的name属性。
在使用[N].xxx语法时,要注意位置序号的含义,它并不是表示“获取栈中索引为N的对象”,而是截取从位置N开始的部分栈。

因为根栈结构是一个ArrayList,根据栈的数据结构,访问一个值是不断pop掉栈顶的值来做到访问该list的对象

4、访问静态成员
除了使用标准的OGNL表达式访问静态字段和静态方法(struts2从某版本开始需要在常量中注册struts.ognl.allowStaticMethodAccess 为true 才能调用静态方法)外,Struts2还允许你不指定完整的类名,而是通过“vs”前缀来调用保存在栈中的静态字段和静态方法。
@vs@FOO_PROPERTY
@vs@someMethod()
@vs1@someMethod()

<s: property value="@java.util.UUID@randomUUID()" />
vs表示ValueStack,如果只有vs,那么将使用栈顶对象的类;如果在vs后面跟上一个数字,那么将使用栈中指定位置处的对象类。

5、值栈中的Action实例
Struts2框架总是把Action实例放在栈顶。因为Action在值栈中,而值栈又是OGNL中的根,所以引用Action的属性可以省略“#”标记,这也是为什么我们在结果页面中可以直接访问Action的属性的原因。

 

个人总结:

 

1.首先拿到vs对象有三种方式在这里不说了, 查笔记

2.在actionContext(大Map)中有指向vs的key;而在vs中也有大map的Map<String,Object> getContext()应用 和 一个list;

3.综上所以vs 和 actionContext 构成了OGNL 访问数据的上下文!(一个大map结构!)<s:debug/>访问

4.针对用户每次访问动作类,struts的核心filter都会创建属于自己的vs对象。

////////////////////////////////////

关于ValueStack一些函数用法

 

void set(String key,Object value):先获取根栈栈顶的Map,如果不存在,压入一个新的Map,把keyvalue放到这个Map中。如果存在,直接放keyvalue

 

void setValue(String ognlExp ,Object):String是一个OGNL表达式。如果表达式以#开头,操作contextMap。如果不是,设置根栈中对象的某个属性,从顶到尾依次搜寻

 

Object findValue(String expr):参数是一个OGNL表达式。如果以#开头,从contextMap中找key值所对应的对象。如果不是以#开头,搜索根栈中对象的属性(getter方法)

 

特别注意:如果编写的表达式不是以#开头,先搜索根栈对象的所有属性,如果没有找到,会把它当做key值到contextMap中找

 

 String findString(String expr):findValue功能一样,但把OGNL表达式获取的对象转换成String

 

OGNL valueStack StackContext(ActionContext)深入分析(转+个人理解)

标签:

原文地址:http://www.cnblogs.com/freed0m/p/4793379.html

(0)
(2)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!