什么是值栈
ValueStack是Struts2的一个接口,字面意义为值栈,OgnlValueStack是ValueStack的一个实现类,客户端发起一个请求struts2架构就会创建一个action实例同时创建一个OgnlValueStack值栈实例。OgnlValueStack贯穿整个Action的生命周期,struts2中使用OGNL将请求Action的参数封装为对象储存到值栈中,并通过ONGL表达式读取值栈中的对象属性值
ValueStack其实类似于一个数据中转站(strets2中的数据都在其中)
ValueStack贯穿Action整个生命周期(Action一旦创建了,框架就会创建一个ValueStack对象)
值栈的内部结构
ValueStack主要有两个内部区域
root区域 :其实就是一个ArrayList.里面一般放置对象。获取root对象不需要加#
context区域 :其实就是一个Map.里面放置的是web开发常用对象的数据引用。获取context数据需要加#
request
session
application
parameters
attr
所说的操作值栈,通常指的是操作ValueStack中的root区域
ActionContext和值栈的关系
ServletContext: Servlet的上下文
ActionContext: Action的上下文
Struts2中一个请求过来时,执行过滤器中的doFilter方法,在这个方法中创建ActionContext,
在创建ActionContext中创建ValueStack对象,将ValueStack对象传递到ActionContext中。所以可以通过ActionContext对象获得ValueStack对象
ActionContext对象之所以能够访问Servlet的API(访问的是域对象的数据)。因为在其内部有值栈的引用
值栈的获得
通过ActionContext获取
通过request获取
//通过ActionContext获得
ValueStack valueStack = ActionContext.getContext().getValueStack();
//通过request获得
ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
//一个Action实例只会有一个值栈对象
System.out.println(valueStack ==valueStack2);
操作值栈
方法一对Action中的属性提供Get方法(不常用),因为Action本身就在值栈中,所以我们可以通过对Action属性提供的get方法来操作值栈
public class vs2 extends ActionSupport {
private User user;
public User getUser() {
return user;
}
@Override
public String execute() throws Exception {
//向值栈中存值
user = new User("独孤求败",66666);
return SUCCESS;
}
}
方法二调用值栈中的方法
public class vs3 extends ActionSupport {
//方式二,调用值栈中的方法实现
@Override
public String execute() throws Exception {
//向值栈中保存数据
//获得值栈对象
ValueStack valueStack = ActionContext.getContext().getValueStack();
//使用push(Object obj); set(String key ,Object obj);
User u = new User("客户二",88888);
//现在u会出现在栈顶的位置
valueStack.push(u);
//建立一个Map集合将Map压入栈中
valueStack.set("name", "Map数据");
return super.execute();
}
}
从值栈中获取数据
先存入
public class vs4 extends ActionSupport {
//获取值栈中的数据
@Override
public String execute() throws Exception {
//向值栈中保存一个对象(root中)
User u = new User("获取值栈中数据",123456);
ActionContext.getContext().getValueStack().push(u);
//向值栈中保存一个集合(root中)
List<User> list = new ArrayList<User>();
User u2 = new User("集合数据1",123456);
User u3 = new User("集合数据2",123456);
User u4 = new User("集合数据3",123456);
list.add(u2);
list.add(u3);
list.add(u4);
ActionContext.getContext().getValueStack().set("list",list);
//向Context中存入数据
//获取request对象
ServletActionContext.getRequest().setAttribute("name","r数据");
ServletActionContext.getRequest().getSession().setAttribute("name","s数据");
ServletActionContext.getServletContext().setAttribute("name","a数据");
return SUCCESS;
}
}
获取
<c:debug></c:debug>
<h3>获取一个对象的数据</h3>
<c:property value="username"/>
<c:property value="password"/>
<h3>获取集合中的数据</h3>
<c:property value="list[0].username"/><br>
<c:property value="list[0].password"/><br>
<c:property value="list[1].username"/><br>
<c:property value="list[1].password"/><br>
<c:property value="list[2].username"/><br>
<c:property value="list[2].password"/><br>
<h3>获取Context中的数据</h3>
<c:property value="#request.name"/>
<c:property value="#session.name"/>
<c:property value="#application.name"/>
<c:property value="#attr.name"/>
<c:property value="#parameters.id"/>
EL也能够访问值栈
例如
${username}
EL特殊字符的使用
1。#构造Map集合和UI标签
<h1>OGNL#号的用法</h1>
<h3>获取context的数据</h3>
<%
request.setAttribute("name","C数据");
%>
<c:property value="#request.name"/>
<h3>获取#构建一个Map集合的数据</h3>
<!-- list -->
<c:iterator var="i" value="{'aa','bb','cc'}" >
<!-- 写了var这个属性在值栈的Context区域也会存储一份 -->
<c:property value="i"/>--<c:property value="#i"/><br>
</c:iterator>
<hr>
<!-- Map -->
<c:iterator var="entry" value="#{'aa':'11','bb':'22','cc':'33' }">
<c:property value="key" />--<c:property value="value" /><br>
<c:property value="#entry.key"/>--<c:property value="#entry.value"/><br>
</c:iterator>
<hr>
<!-- 配置单选框 -->
<c:radio list="{'男','女'}" name="sex" label="性别"></c:radio><br>
<!-- Map集合 -->
<c:radio list="#{'1':'男','2':'女' }" name="sex2" label="性别"></c:radio>
2 %强制解析
<h1>强制解析%</h1>
<%request.setAttribute("name","张三"); %>
<c:textarea name="name" value="%{#request.name}"></c:textarea>
3。$符号