valueStack(值栈)
值栈
值栈(ValueStack)就是 OGNL 表达式存取数据的地方。在一个值栈中,封装了一次请求所需要的所有数据。
在使用 Struts2 的项目中,Struts2 会为每个请求创建一个新的值栈,也就是说,值栈和请求是一一对应的关系,这种一一对应的关系使值栈能够线程安全地为每个请求提供公共的数据存取服务。
值栈的作用
值栈可以作为一个数据中转站在前台与后台之间传递数据,最常见的就是将 Struts2 的标签与 OGNL 表达式结合使用。
值栈实际上是一个接口,在 Struts2 中利用 OGNL 时,实际上使用的就是实现了该接口的 OgnlValueStack 类,这个类是 OGNL 的基础。
值栈的生命周期
值栈贯穿整个 Action 的生命周期,每个 Action 类的对象实例都拥有一个 ValueStack 对象,在 ValueStack 对象中保存了当前 Action 对象和其他相关对象。
Struts2 框架把 ValueStack 对象保存在一个名为 struts.valueStack 的 request 属性中,也就是说,值栈与 Action 的生命周期一致。值栈的生命周期随着 request 的创建而创建,随着 request 的销毁而销毁。
值栈的获取方式
要获取值栈中存储的数据,首先应该获取值栈。值栈的获取有两种方式:
● 在request中获取值栈:
ValueStack 对象在 request 范围内的存储方式为 request.setAttribute("struts.valueStack",valuestack),可以通过如下方式从 request 中取出值栈的信息。
//获取 ValueStack 对象,通过 request 对象获取
ValueStack valueStack = (ValueStack)ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
ServletActionContext.STRUTS_VALUESTACK_KEY 是 ServletActionContext 类中的常量,它的值为 struts.valueStack。
● 在ActionContext中获取值栈:
在使用 Struts2 框架时,可以使用 OGNL 操作 Context 对象从 ValueStack 中存取数据,也就是说,可以从 Context 对象中获取 ValueStack 对象。实际上,Struts2 框架中的 Context 对象就是 ActionContext。
ActionContext 获取 ValueStack 对象的方式:
//通过 ActionContext 获取 valueStack 对象
ValueStack valueStack = ActionContext.getContext().getValueStack();
ActionContext 对象是在 StrutsPrepareAndExcuteFilter 的 doFilter() 方法中被创建的,在源码中用于创建 ActionContext 对象的 createActionContext() 方法内可以找到获取的 ValueStack 对象的信息。
方法中还有这样一段代码:
ctx=new ActionContext(stack.getContext());
//stack.getContext()返回的是一个Map<String,Object>,根据此Map构造一个ActionContext
ValueStack 对象中的 Context 对象被作为参数传递给了 ActionContext 对象,这也就说明 ActionContext 对象中持有了 ValueStack 对象的引用,因此可以通过 ActionContext 对象获取 ValueStack 对象。
Struts2值栈内部结构详解
ValueStack 对象的内部有两个逻辑部分
● ObjectStack(root 栈):是 CompoundRoot 类型,用 ArrayList 定义,Struts2 把动作和相关对象压入 ObjectStack 中。
● ContextMap(Map 栈):是 OgnlContext 类型,是一个 Map 集合,Struts2 把各种各样的映射关系(一些 Map 类型的对象)压入 ContextMap 中。
通过运行项目查看 ValueStack 中的信息
首先,在 struts2Demo05 项目的 com.mengma.ognl 包中新创建一个名称为 ValueStackAction 的类,并在类中编写一个获取 ValueStack 对象的方法。
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class ValueStackAction extends ActionSupport {
public String execute() throws Exception {
// 通过ActionContext获取valueStack对象
ValueStack valueStack = ActionContext.getContext().getValueStack();
System.out.println(valueStack);
return SUCCESS;
}
}
然后,将新建的 Action 信息添加到 struts.xml 中。
<action name="valueStack" class="com.mengma.ognl.ValueStackAction">
<result name="success">index.jsp</result>
</action>
最后,在 ValueStackAction 类中的第 11 行处设置断点,以 Debug 模式启动项目。在浏览器的地址栏中输入地址 http://localhost:8080/struts2Demo05/valueStack.action后,MyEclipse 会进入 Debug 模式。从 Variables 窗口中可以看到 valueStack 的结构信息。
如图所示的 ValueStack 结构中,只需关注 context 对象和 root 对象。从图中可以看到,context 对象的类型为 OgnlContext,root 对象的类型为 CompoundRoot。如果要查看这两个类的源码,则可以看到如下语句:
OgnlContext extends Object implements Map
CompoundRoot extends ArrayList
从上述两个类的源码中可以看出,context 对象实际上就是一个 Map,root 对象实际上就是一个 ArrayList。也就说明了 ValueStack 的两个逻辑部分 ObjectStack 对应 ArrayList(root),ContextMap 对应 Map(context)。
映射关系:
一般情况下,root 对象在存储 Action 的相关信息时会把相关的映射压入 ContextMap 中,这些相关的映射具体如下。
- parameters:该 Map 中包含当前请求的请求参数。
- request:该 Map 中包含当前 request 对象中的所有属性。
- session:该 Map 中包含当前 session 对象中的所有属性。
- application:该 Map 中包含当前 application 对象中的所有属性。
- attr:该 Map 按如下顺序检索某个属性:request,session,application。
需要注意的是,在 context 对象中包含了 root 对象,从 context 对象的结构中就可以查看到相关信息
从图中可以看到 context 对象中的 root 对象,这也就证明了 context 对象中包含了 root 对象,并且该对象的类型为 CompoundRoot。
Struts2获取值栈数据
在 Struts2 中,值栈的主要作用就是解决从 Action 到页面的数据交换问题。在采用属性驱动和模型驱动交换数据时,Struts2 会将对象自动存储到 ValueStack 中。
● 属性驱动:每次请求访问 Action 的对象时,Action 中的属性对象会被自动压入 ValueStack 中。
● 模型驱动:Action 如果实现了 ModelDriven 接口,那么 ModelDrivenInterceptor 拦截器会生效,会将 model 对象压入到 ValueStack 中。
属性对象或 model 对象存储到 ValueStack 中后,就可以直接从 ValueStack 中获取页面所需的数据。
属性驱动
1.创建实体类 User
创建一个名称为 User 的类,该类中包含 name 和 age 两个属性,以及其 getter 和 setter 方法。
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
创建 Action
创建一个名称为 ValueStack2Action 的类
import com.mengma.domain.User;
import com.opensymphony.xwork2.ActionSupport;
public class ValueStack2Action extends ActionSupport {
private static final long serialVersionUID = -6671554902053439423L;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String execute() throws Exception {
return SUCCESS;
}
}
声明了一个 User 类型的属性 user 及其 getter 和 setter 方法,由于只进行存取值的操作,所以直接使用 Action 的 execute() 方法返回 SUCCESS 即可。
修改配置文件
在配置文件 struts.xml 的 <package> 元素中,增加 action 的配置信息
<action name="valueStack2" class="com.mengma.ognl.ValueStack2Action">
<result>/field.jsp</result>
</action>
创建页面文件
在项目的 WebContent 目录下创建一个名称为 field.jsp 的文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>属性驱动方式获取值栈中的数据</title>
</head>
<body>
<s:debug></s:debug>
姓名:<s:property value="user.name"/><br/>
年龄:<s:property value="user.age"/>
</body>
</html>
编写了一个 <s:debug> 标签,用于查看值栈的信息,然后分别使用 <s:property> 标签获取用户的姓名和年龄。
启动项目并查看结果
从请求地址中传入的参数值已经成功地在页面中显示出来,这就是使用属性驱动获取 ValueStack 中对象的方式;
User 对象传入 Action 对象时,会被自动压入 ValueStack 中,所以在 Action 的 execute() 方法中不存储值也能在页面取出。
此时单击 Debug 标签链接便可以查看到值栈中的参数传递情况:
在参数列表中可以到 Property Name 列表中的参数 user 就是页面中获取的对象,在 Property Value 中包含了 user 的属性值。
模型驱动
采用模型驱动的方式时,Struts2 会将 Action 中的 model 信息存入到值栈中。
创建 Action
创建一个名称为 ValueStack3Action 的类
import com.alin.mengma.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class ValueStack3Action extends ActionSupport implements ModelDriven<User> {
private User user = new User();
@Override
public User getModel() {
return user;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String execute() throws Exception {
return SUCCESS;
}
}
创建了一个 User 类型的对象 user,实现了 ModelDriven 接口的 getModel() 方法,并在 getModel() 方法中返回 user 对象,这样就可以接收到和 user 对象中属性名称相同的参数的值。
修改配置文件
在配置文件 struts.xml 的 <package> 元素中,增加 action 的配置信息
<action name="valueStack3" class="com.mengma.ognl.ValueStack3Action">
<result>/model.jsp</result>
</action>
创建页面文件
创建一个名称为 model.jsp 的页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>模型驱动方式获取值栈中的数据</title>
</head>
<body>
<s:debug></s:debug>
姓名:<s:property value="name"/><br/>
年龄:<s:property value="age"/>
</body>
</html>
启动项目并查看结果
从请求中传入的参数 name 和 age 已经成功地在页面中显示出来。由于是模型驱动,所以不需要用 user.name 的形式传递参数;
接下来单击 Debug 链接查看 ValueStack 中存储的参数值:
从下图中可以看出,采用模型驱动的方式时,User 对象的信息被存储在值栈的栈顶。由于 Action 中提供了一个 getModel() 方法,所以使用模型驱动时可以从 Action 中获取 model 对象,而在传递参数时,直接用 name 和 age 即可,这就是采用模型驱动获取值栈中数据的方式。
通过EL访问值栈的数据
在 Struts2 框架中,使用 EL 表达式也可以直接访问值栈中的数据。
<hr/>
使用EL表达式访问值栈中的数据:<br/>
姓名:${model.name }<br/>
年龄:${model.age }
使用了 EL 表达式获取值栈中的数据,重新访问页面后
直接用 EL 表达式的方式同样取出了值栈中的数据。EL 表达式能够访问值栈中数据的原因,是因为 Struts2 框架对请求进行了增强,如果在 request 作用域中没有查找到对应的值,就会到值栈中查找。查找时,它会先被当作属性在 root 中查找,查找不到再被当作 key 在 contextMap 中查找对应的 value,查找到后会将数据取出。
valueStack(值栈)的更多相关文章
- Struts 中 ActionContext ctx.put()把数据放到ValueStack里之数据传输背后机制:ValueStack(值栈)
1. 数据传输背后机制:ValueStack(值栈) 在这一切的背后,是因为有了ValueStack(值栈)! ValueStack基础:OGNL要了解ValueStack,必须先理解OGNL ...
- ValueStack值栈和ActionContext
Struts2在OGNL之上提供的最大附加特性就是支持值栈(ValueStack),在OGNL上下文中只能有一个根对象,Struts2的值栈则允许存在许多虚拟对象. 一:值栈(ValueStack) ...
- [ SSH框架 ] Struts2框架学习之三(OGNl和ValueStack值栈学习)
一.OGNL概述 1.1 什么是OGNL OGNL的全称是对象图导航语言( object-graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可 ...
- Struts2——(3)ValueStack(值栈)
一.ValueStack 主要用于存储请求相关信息,内部结构如下 root区:被称为根存储区,是一个栈结构,栈顶元素为当前请求的Action对象. context区:被称为变量存储区,是一个Map结构 ...
- [转]Struts2数据传输的背后机制:ValueStack(值栈)
1. 数据传输背后机制:ValueStack(值栈) 在这一切的背后,是因为有了ValueStack(值栈)! 2. ValueStack基础:OGNL 要了解ValueStack,必须先理解OGNL ...
- Struts2数据传输的背后机制:ValueStack(值栈)
1. 数据传输背后机制:ValueStack(值栈) 在这一切的背后,是因为有了ValueStack(值栈)! ValueStack基础:OGNL 要了解ValueStack,必须先理解OGN ...
- 【Java EE 学习 36】【struts2】【struts2系统验证】【struts2 ognl值栈】【struts2 ongl标签】【struts2 UI标签】【struts2模型驱动和令牌机制】
一.struts2系统验证 1.基于struts2系统验证的方式实际上就是通过配置xml文件的方式达到验证的目的. 2.实际上系统校验的方法和手工校验的方法在底层的基本实现是相同的.但是使用系统校验的 ...
- OGNL表示式使用和值栈
另外值得参考博客:http://blog.csdn.net/resigshy/article/details/7560573 OGNL是Object Graphic Navigation Langua ...
- [原创]java WEB学习笔记59:Struts2学习之路---OGNL,值栈,读取对象栈中的对象的属性,读取 Context Map 里的对象的属性,调用字段和方法,数组,list,map
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- Sublime text2 + cygwin编译C++
1.安装cygwin2.安装sublime text23.将g++和gdb加入系统环境变量(windows系统)3.安装package control4.通过package control安装subl ...
- hive 总结一
本文参考:黑泽君相关博客 本文是我总结日常工作中遇到的坑,结合黑泽君相关博客,选取.补充了部分内容. 上传数据 上传数据后执行修复 msck 命令 上传数据 hive> dfs -mkdir - ...
- Appium测试过程中,建议使用谷歌输入法。用搜狗输入法报错报找不到元素,卡住
1. 手机使用谷歌输入法,在登录页面输入密码时输入数字时卡住报错 代码: 手机卡住 页面:看到页面上没有显示数字,所以卡住报错
- 19.SimLogin_case04
# 利用cookies登录马蜂窝 import requests from lxml import etree session = requests.Session() phone_number = ...
- 02-python 学习第二天
今天学习了以下几个方面的内容,虽然部分内容不能理解,跟着老师写出了代码. 列表.元组操作 字符串操作 字典操作 集合操作 文件操作 字符编码与转码 程序练习1:购物车程序 请闭眼写出以下程序. 程序: ...
- USACO training course Mother's Milk /// DFS(有点意思) oj10120
题目大意: 输入 A B C 为三个容器的容量 一开始A B是空的 C是满的 每一次倾倒只能在 盛的容器满 或 倒的容器空 时才停止 输出当A容器空时 C容器内剩余量的所有可能值 Sample Inp ...
- js把时间转化为 ‘2019-07-01’ 格式
将new Date()数据转化为‘2019-07-01’格式 //时间 function formatDate(date) { var y = date.getFullYear(); ; m = m ...
- Loadrunner学习---脚本编写(1)
Loadrunner学习---脚本编写(1) 中午看了两集<奋斗>发现越看越想看,但是想到好不容易没上班,在家还是赶紧学习下LR的知识吧.下面这个网页的文章原来也是看过的,但发现没几天就忘 ...
- 手势UIGestureRecognizer
UIGestureRecognizer抽象类,六大手势是其子类: UITapGestureRecognizer 点击 UIPinchGestureRecognizer 缩放 ...
- JEECG 4.0 版本发布,JAVA快速开发平台
JEECG 4.0 版本发布,系统全面优化升级,更快,更稳定! 导读 ⊙平台性能优化,系统更稳定,速度闪电般提升 ...