值栈的概述
1、什么是值栈
Struts2将XWork对Ognl的扩展这一套机制封装起来,这个对象叫ValueStack。
ValueStack实际上就是一个容器。
它由Struts框架创建,当前端页面如jsp发送一个请求时,Struts的默认拦截器会将请求中的数据进行封装,并入ValueStack的栈顶。
ValueStack是Struts的一一个接口,字面意义为值栈,OgnIValueStack 是ValueStack 的实现类,客
户端发起一个请求struts2 架构会创建一个action 实例同时创建-一个OgnIValueStack 值栈实例,OgnlValueStack贯穿整个Action 的生命周期,struts2 中使用OGNL将请求Action的参数封装为对象存储到值栈中,并通过OGNL表达式读取值栈中的对象属性值。
简化理解ValueStack其实类似一个数据的中转栈(Strust2框架当中的数据就都保存到了ValueStack中)
ValueStack接口,实现类OgnlValueStack的对象。
ValueSatck贯穿整个Action的生命周期。(Action一旦创建了,框架就会创建一个ValueStack对象)
放入值栈的数据可以在任何位置取出来(JSP、Servlet、Action、配置文件,在Struts2的任何地方都可以取到)
2、值栈的内部结构
ValueStack当中有两个主要的区域:
root区域: 其实就是一个ArrayList。里面一般放置的对象。获取root的数据是不需要加#
context区域:其实就是一个Map。里面放置的是Web开发的一些常用的对象数据的引用。获取的是context当中的数据是需要加#
requets:
session:
application:
parameters:
attr:
所说的操作值栈,通常指的是操作的是ValueStack当中的root区域。
创建一个类继承ActionSupport
public class ValueStackDemo1 extends ActionSupport {
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
//获得值栈的对象
ValueStack valueStack = ActionContext.getContext().getValueStack();
return SUCCESS;
}
}
设置跳转页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>查看值栈的内部结构</h1>
<s:debug></s:debug>
</body>
</html>
结果页面的数据
3、值栈与ActionContext的关系
ServletContext:Servlet的上下文。(贯穿整个应用的对象)
ActionContext:Action的上下文。(贯穿整个应用的对象)
通过源码查看到:当请求过来的时候,执行过滤器当中的doFilter方法,在这个方法当中创建ActionContext,
在创建ActionContext的过程当中,创建ValueStack对象,将ValueStack对象传递给ActionContext对象。
所以我们可以通过ActionContext来获取值栈的对象。
ActionContext这个对象之所以能够访问到Servlet的API(访问的是域对象当中的数据)。因为在其内部有值栈的引用
//获得值栈的对象
ValueStack valueStack = ActionContext.getContext().getValueStack();
4、获得值栈
(1)第一种:通过ActionContext对象来获取值栈对象。
在Struts2内部,将值栈存入到request中一份。
// 第一种:通过ActionContext获得:
ValueStack valueStack = ActionContext.getContext().getValueStack();
(2) 第二种:通过request对象来获得
// 第二种:通过request对象来获得
ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
(3) 测试两个对象是不是同一个对象
一个Action的实例,只会创建一个ValueStack的对象(一个ValueStack只会为一个Action服务)
public class ValueStackDemo2 extends ActionSupport {
@Override
public String execute() throws Exception {
// 第一种:通过ActionContext获得:
ValueStack valueStack1 = ActionContext.getContext().getValueStack();
// 第二种:通过request对象来获得
ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest()
.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
System.out.println(valueStack1 == valueStack2);
return NONE;
}
}
浏览器访问
表示两个方式获取的Action是同一个值栈对象
5、操作值栈-向值栈当中存入数据(Root当中)
(1)第一种:在Action当中提供属性的get方法的方式。
默认的情况下,将Action对象压入到值栈。Action都在值栈当中,那么Action的属性一定也在值栈当中。
/*
* 操作ValueStack:方式一:利用Action本身在值栈当中本身的特性。
*/
public class ValueStackDemo3 extends ActionSupport {
private User user;
public User getUser() {
return user;
}
@Override
public String execute() throws Exception {
// 向ValueStack中去存值
user = new User("李峰", "222");
return SUCCESS;
}
}
配置文件
jsp页面
可以在Root当中得到对应的user对象
(2)第二种:使用ValueStack当中本身的一些方法的方式。
import com.itzheng.struts2.domain.User;
import com.opensymphony.xwork2.ActionContext;
/*
* 操作值栈:方式二:调用值栈当中的方法来进行实现。
*/
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class ValueStackDemo4 extends ActionSupport {
@Override
public String execute() throws Exception {
//向值栈保存数据:
//获得值栈对象
ValueStack valueStack = ActionContext.getContext().getValueStack();
//一般会使用值栈当中的两个对象
//使用push(Object obj); set(String key,Object obj);
User user = new User("李四","121212");
//压栈,user在栈顶的位置
valueStack.push(user);
return super.execute();
}
}
User在栈顶
注意:通过set的方式将输入放入到栈当中
谁最后调用谁就在最上面,创建了一个MAP集合,将MAP集合压入到栈当中
6、获取值栈的是数据
(1)获取root当中的数据:不需要加#
获取值栈当中数据就是在页面当使用OGNL表达式即可。
获取对象的数据
浏览器页面上
保存并获取集合当中的数据
public class ValueStackDemo5 extends ActionSupport {
@Override
public String execute() throws Exception {
// 向值栈当中保存对象
User user = new User("aaa", "123");
ActionContext.getContext().getValueStack().push(user);
// 同值栈中保存一个集合
List<User> list = new ArrayList<User>();
list.add(new User("aaa", "111"));
list.add(new User("bbb", "222"));
list.add(new User("ccc", "333"));
ActionContext.getContext().getValueStack().set("list", list);
return super.execute();
}
}
(2)获取context当中的数据:不需要加#
(3)拓展内容
注意如果是arrt.name那么获取的是栈值当中的栈顶元素(也就是第一个元素)
parameters.id的作用是接收参加