值栈对象的创建,ValueStack和ActionContext的关系
- 值栈对象是请求时创建的
- ActionContext是绑定到当前的线程上,那么在每个拦截器或者Action中获取到的ActionContext是同一个。
- ActionContext中存在一个Map集合,该map集合和ValueStack的ContextMap是同一个地址
- ActionContext中可以获取到ValueStack的引用
获取值栈对象的方式
- ValueStack vs1 = (ValueStack) ServletActionCotext.getRequest().getAttribute(“struts.valueStack”);
- ValueStack vs2 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
- ValueStack vs3=ActionContext.getContext().getValueStack();
向值栈中保存数据(主要针对root栈)
valueStack.push(Object.obj);
- push 方法的底层调用root对象的push方法(把元素添加到0位置)
valueStack.set(String key,Object obj);
- 源码获取map集合(map有可能是已经存在的,有可能是新创建的),把map集合push到栈顶,再把数据存入到map集合中
在jsp中通过
<s:debug/>
查看值栈的内容
<h3>从值栈当中获取值</h3>
<%--
<s:property value="[1].top"/>
--%>
<%--<s:property value="[0].top.msg"/>--%>
<%--<s:property value="[0].top.username"/>--%>
<!--[0].top可以省略-->
<s:property value="username"/>
<!--迭代标签,属性的名称-->
<!--value 要迭代的集合,需要从值栈中获取-->
<!--var 迭代过程中,遍历的对象,var可以写也可以不写,把迭代产生的对象默认压入到context栈中,从context栈取值,要加#号-->
<!--var,不编写,默认把迭代产生的对象压入到root栈中-->
<s:iterator value="ulist" var="u">
<s:property value="#u.username"/>
</s:iterator>
<s:iterator value="ulist">
<s:property value="[0].top.username"/>
<s:property value="password"/>
</s:iterator>
<!--可以从JSP中-->
<s:debug></s:debug>
public class ValueStackAction extends ActionSupport{
public String execute(){
//使用获取值栈对象
/* HttpServletRequest request = ServletActionContext.getRequest();
Object vs = (ValueStack)request.getAttribute("struts.valueStack");
System.out.println(vs);*/
//获取值栈对象,先获取ActionContext对象
ValueStack vs = ActionContext.getContext().getValueStack();
System.out.println(vs);
// 存入数据
vs.push("梅梅");
//栈顶
vs.set("msg","美美");
vs.set("info","小蒋");
return SUCCESS;
}
//
public String save(){
//获取值栈对象
ValueStack vs = ActionContext.getContext().getValueStack();
//压栈
// vs.push("meimei");
// vs.set("msg","小米");
//创建User对象,压栈
// User user = new User("meiemi","123");
// vs.push(user);
// vs.set("user",user);
List<User> ulist = new ArrayList<User>();
ulist.add(new User("熊大","123"));
ulist.add(new User("熊二","345"));
ulist.add(new User("熊三","456"));
vs.set("ulist",ulist);
return SUCCESS;
}
}
在jsp中获取值栈的数据
总结:
- 访问root中的数据,不需要#
- 访问context其他对象数据,加#
- 如果向root中存入对象的话,优先使用push方法
- 如果向root中存入集合的话,优先要使用set方法
在OgnlContext中获取数据
- 在Action中向域中存入值
request:<s:property value ="#request.username"/>
session:<s:property value="#session.username"/>
application:<s:property value="#application.username"/>
attr:<s:property value="#attr.username"/>
parameters:<s:property value ="#parameters.cid"/>
EL 表达式也会获取到值栈的数据
StrutsPreparedAndExecuteFilter的doFilter代码中 request = prepare.wrapRequest(request);
- 对Request对象进行了包装,StrutsRequestWrapper
- 增强了request的getAttribute
Object attribute = super.getAttribute(s);
if(attribute==null){
attribute=stack.findValue(s);
}
- 访问request范围的数据时,如果数据找不到,去值栈中找
- request对象,具备访问值栈数据的能力(查找root的数据)