1.什么是ValueStack
对于每一个action的调用,Struts在执行相应的动作方法之前会先创建一个名为ValueStack的对象。Value Stack用来保存该动作对象或者对象。由于最终在执行Action类相应的action方法之前,拦截器需要先访问ValueStack。视图也需要访问ValueStack。Struts框架将其保存在一个名为struts.valueStack的请求属性中。
2.获取valueStack的三种方法:
ValueStack v1 = ActionContext.getContext().getValueStack();
ValueStack v2 = ServletActionContext.getValueStack(ServletActionContext.getRequest());
ValueStack v3 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
- 1
- 2
- 3
- 4
打印其HashCode码一模一样。
说明:
1、 值是一样的,说明只有一个对象
2、 因为有一种是从request域中获取的,所以是一次请求
3.ValueStack的内容
valueStack分为对象栈(Object Stack)和Map栈(Context Map).
Struts将把动作和相关对象压入Object Stack,而把各种各样的映射关系压入Context Map。
通常说的ValueStack就是指Object Stack,它是一个真正数据结构意义的栈。Object Stack也常常被称为root(其实是一个ArrayList)。Context Map我们一般称其为context(是一个HashMap)它是整个OGNL其中包括了root
4.OGNL中的两种对象
OGNL中包含两种对象,即_root和_value.
_value即:request, session, application, parameters, attr等命名对象,但这些命名对象都不是根。
_root即:当前请求的Action实例等
“根”对象和普通命令对象的区别在于:
“根”对象(root) 对象栈: 实际上是 CompoundRoot 类型, 是一个使用 ArrayList 定义的栈. 里边保存各种和当前 Action 实例相关的对象(如果这个Action实例包括域对象的话域对象会进root).是一个数据结构意义的栈.
1)访问Context Map里的对象需要在对象名之前添加 #
2)访问Object Stack对象的属性时,可以省略#而直接通过属性名来搜索
说明:
从上图中也可以看出valueStack总共分为两个部分:
对象栈:root (CompoundRoot类)
Map栈:_values和_root (OgnlContext 类)
5.Struts会把当前访问的Action实例压入值栈栈定
压入时间点为:
由于Struts2最后终将调用Action类中的action方法。但在调用此方法之前:
*先创建一个StrutsActionProxy (ActionProxy默认实现的子类)
*在创建StrutsActionProxy之后,对其进行初始化,把Action对象压入值栈
在调用该方法前该Action被压入栈顶,如果在初始化的过程中,在Action的构造函数中又初始化了其他类,这这个类也会被压入值栈。所以最后栈顶的元素会是这个新初始化的类。
6.ValueStack中对象的存取
Object Stack 的存放: push 或者 add:
将一个对象放入Object Stack的栈顶:
ActionContext.getContext().getValueStack().push(object);
ActionContext.getContext().getValueStack().getRoot().add(0,object);
- 1
- 2
Object Stack的提取: peek() 或 pop()
peek()取得的是栈顶元素:
Object object = ActionContext.getContext().getValueStack().peek();
- 1
Object Stack的元素的弹出:pop:
Object object = ActionContext.getContext().getValueStack().pop();
- 1
7.动态修改ValueStack中对象的属性
说明:
可以利用valueStack.setParameter方法改变对象栈中对象的属性的值。至于匹配哪个。则依次从对象栈的栈顶向下搜索,找到匹配的就修改