对于Struts2中的值栈的学习,主要是要搞清楚以下几个对象间的关系:
- 值栈与ActionContext的关系
- 值栈与值栈的Context属性的关系
- 值栈的Context属性与ActionContext的关系
- 值栈对象
- 值栈的实现类
在用户提交一个Action请求后,系统会马上创建两个对象:Action实例与值栈对象。Struts2中的值栈ValueStack是个接口,其实现类为OgnlValueStack。
通过OgnlValueStack类的源码,可以知道OgnlValueStack类中包含两个成员:root与context。
context属性的创建
在创建值栈对象时,系统调用了OgnlValueStack的构造器,而该构造器调用了setRoot()方法。
值栈的属性context的类型为 Map< String,Object >,查看OgnlValueStack类的setRoot()方法源码可以看到,在初始化root的同时创建了context对象。
setRoot()方法里,系统创建了两个数据结构:一个栈(root),一个Map(context)
创建的这个栈,即root对象,就是值栈对象所拥有的真正的用于存放根对象的栈。为了方便对于当前Action的访问,就将当前Action实例直接放入到了该栈中。
创建的这个Map,即context对象,在Struts2中是个很重要的对象,需要经常访问。但若要访问这个context Map,就需要首先获取到值栈对象,然后再通过值栈获取到这个context Map。为了方便这个context Map的获取,就给这个context定义了另一个名称 —- ActionContext。通过ActionContext的方法getContext()就可直接获取到该context Map。
在创建了context后,马上将当前值栈对象放入到其中,并且给予了固定的key,与专门的获取值栈对象的方法getValueStack()。
OgnlValueStack中的VALUE_STACK
public static final String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";
ActionContext中定义的常量VALUE_STACK,其值与OgnlValueStack中的该常量值相同
public static final String VALUE_STACK = ValueStack.VALUE_STACK;
OgnlValueStack中用于获取值栈对象的方法getValueStack()。其底层也是执行了map.get(key)操作
public ValueStack getValueStack() {
return (ValueStack) get(VALUE_STACK);
}
public Object get(String key) {
return context.get(key);
}
所以,ActionContext这个Map中,最终存放着如下内容:
注意:ValueContext中的context存放的是ActionContext的地址,并不是ActionContext本身