值栈就是OGNL表达式存取数据的地方,Struts2是在有请求到达的时候为每个请求创建一个新的值栈,也就是说值栈和请求是一一对应的,值栈封装了一次请求所需要的所有数据,这种一一对应的关系是值栈能够线程安全的为每个请求提供公共的数据存取服务。
值栈主要用于把数据带到JSP。
ValueStack贯穿整个Action的声明周期,每个Action类的对象实例都拥有一个ValueStack对象,在其中保存当前Action对象和其他相关的对象。Struts2框架把ValueStack对象保存在名为“struts.valueStack”的request属性中,也就是说,ValueStack与Action的生命周期保持一致,ValueStack的生命周期是随着request的创建而创建的,随着request的销毁而销毁的。
在ActionContext中获取值栈
OGNL中含有一个上下文对象Context,程序中可以使用OGNL操作这个上下文对象,从ValueStack中存储和取出数据,这就说明可以从上下文对象中获取到ValueStack对象。在Struts2中,这个Context对象其实就是ActionContext。
ValueStack valueStack=ActionContext.getContext().getValueStack();
值栈的内部结构
- ObjectStack(对象栈):是CompoundRoot类型,用ArrayList定义,Struts2把action对象和相关对象(action包含的那些属性)压入ObjectStack。(root)
- ContextMap(Map栈):是OgnlContext类型,是个Map集合,Struts2把各种各样的映射关系(一些Map类型的对象)压入ContextMap中。(context)
root对象用来存储Action的相关信息。context存储相关映射,那些web对象。
- parameters:该Map中包含当前请求的请求参数。
- request:request对象
- session:session对象
- application:application对象
- attr:该Map按如下顺序来检索某个属性:request,session,application
在context对象中包含root对象
在开发中的应用
采用属性驱动或模型驱动时,Struts2会将对象自动存储到ValueStack中
- 属性驱动:每次请求访问Action对象时,Action中的属性对象会被自动压入ValueStack中。
- 模型驱动:会将model对象压入ValueStack中。
对象存储到ValueStack中后,页面所需的数据可以直接从ValueStack中获取。
1.属性驱动
public class Product{
private String name;
private String price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}
public class ValueStackAction extends ActionSupport{
private Product p;
public Product getP(){
return p;
}
public void setP(Product p){
this.p=p;
}
public String execute() throws Exception{
p.name="a";
p.price="10";
return SUCCESS;
}
}
<body>
<s:property value="p.name"/>
<s:property value="p.price"/>
</body>
2.模型驱动
public class ValueStackAction extends ActionSupport implements ModelDriven<Product>{
private Product p=new Product();
public Product getModel(){
return p;
}
public String execute() throws Exception{
p.name="a";
p.price="10";
return SUCCESS;
}
}
<body>
<s:property value="model.name"/>
<s:property value="model.price"/>
</body>
模型驱动的方式,将Product对象以model方式直接存储在值栈的栈顶。
通过EL访问值栈的数据
在Struts2中,同样支持使用EL表达式直接访问值栈中的数据。
${model.name}
EL表达式默认支持在4个作用域取值,分别是page、request、session和application,EL表达式能够访问值栈中数据的原因,就是因为Struts2对request进行了增强,如果在request作用域中没有查找到对应的值,就去值栈中查找,找到后会将数据取出。在请求范围内找不到时,先作为属性在root中找,找不到会作为key到contextMap中找对应的value。