Struts2 之值栈
值栈(ValueStack)
http://www.cnblogs.com/bgzyy/p/8639893.html 这是我的有关 struts2 的第一篇文章,对于里面我们说到的一个 struts2 HelloWorld 小练习,即在输入框输入信息提交后在另外一个页面显示输入的信息,显示页面的代码如下:
UserName: ${userName}<br>
Email: ${email}<br>
Address: ${address}<br>
为什么这样一个简单的标签就可以获取到另外一个页面的输入信息,我们使用上面链接中的代码并在其基础上加以改进以得到答案!
我们知道 struts 默认的请求类型为 dispatcher,即请求转发,那么我们尝试在 show.jsp 中利用 request 域对象打印输入值,如下(在前面加上标识以区分):
UserDesc: ^+^<%= request.getAttribute("userDesc")%><br>
结果如下图:

我们可以看到利用 request 的 getAttribute() 方法打印的结果和使用标签一样,此时我们应该想到将 request 打印出来,代码以及结果如下:
Request: <%= request%>

如上图所示,此时的 request 是已经被 struts2 封装的 request,在 IDEA 中双击 Shift 查找 StrustsRequestWrapper 源代码,找到其 getAttributte() 方法,如下:
public class StrutsRequestWrapper extends HttpServletRequestWrapper {
public Object getAttribute(String key) {
if (key == null) {
throw new NullPointerException("You must specify a key value");
}
if (disableRequestAttributeValueStackLookup || key.startsWith("javax.servlet")) {
// don't bother with the standard javax.servlet attributes, we can short-circuit this
// see WW-953 and the forums post linked in that issue for more info
return super.getAttribute(key);
}
ActionContext ctx = ActionContext.getContext();
Object attribute = super.getAttribute(key);
if (ctx != null && attribute == null) {
boolean alreadyIn = isTrue((Boolean) ctx.get(REQUEST_WRAPPER_GET_ATTRIBUTE));
// note: we don't let # come through or else a request for
// #attr.foo or #request.foo could cause an endless loop
if (!alreadyIn && !key.contains("#")) {
try {
// If not found, then try the ValueStack
ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.TRUE);
ValueStack stack = ctx.getValueStack();
if (stack != null) {
attribute = stack.findValue(key);
}
} finally {
ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.FALSE);
}
}
}
return attribute;
}
}
- 如上代码所示,我们可以知道 StrutsRequestWrapper 继承自 HttpServletRequestWrapper
- getAttribute() 方法首先判断传入的 key 是否为空,若是抛出空指针异常
- 若不是判断传入的 key 值是否满足一定的条件,若满足则直接使用父类的 getAttribute() 方法,获取对应的属性值
- 若不满足则经过一系列判断后获取到 ValueStack 对象 stack,从 stack 对象中获得对应 key 的属性,并返回
为了一探究竟我们 Debug 一步步调试查看,首先 Debug 运行程序,在输入页面输入信息之后再在源代码页面上打断点(在源代码页面的 ValueStack 前一行打断点),再点击提交将会跳转到调试页!
- 第一次运行至断点结果如下图所示,这是 struts2 初始化一些必要的信息

- 将光标放置在断点行,点击 Run to Cursor(运行至光标处),直到 key 的值为 userName,再点击将依次 userDesc 等,如图

- 此时点击Step Over 执行代码到下一行,ValueStack 对象将被初始化,如下图所示,在这里我们依次打开 stack,root 在这里我们可以看到一对一对的 key 和 value ,进而我们得知显示页面的值是从此处得来的

- 一些关于值栈的概念
- ValueStack(值栈):贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个 ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前 Action 对象和其他相关对象.
- 在 ValueStack 对象的内部有两个逻辑部分,ObjectStatck 和 ContextMap;
- struts 把 Action 和相关对象(如上例中的 Info 对象)压入ObjectStack 中,这里所说的 ObjetcMap 即上图中的 root,遵循“先进后出” 的原则
- ContextMap:Struts 把各种映射关系压入 ContextMap 中,实际上就是一些对 ActionContext 的引用(parameters、request、session、application、attr)
至此我们得知显示页面的底层实现,即从 ValueStack 中获取,其默认从栈顶开始寻找与 key 值匹配的属性,依次往下,也了解到值栈的基本概念,接下来让我们着手利用 OGNL 获取值栈里对象的属性。
OGNL
在 JSP 页面上利用 OGNL 访问值栈里对象的属性,若希望访问值栈中 ContextMap 中的数据,需要给 OGNL 表达式前面加上一个前缀 #,如果没有添加将会在 ObjectStack 中进行,如下示例在 session 内找 key 为 sessionMap 的属性
<s:property value="#session.sessionMap"/>
property 标签
- Struts2 的 property 标签用来输出值栈中的一个属性值
- 其属性 value 表示来自栈顶对象在页面上将要显示的值(String 类型)
- 其属性 default 表示若 value 若为空,将显示该值(String 类型)
- 其属性escape 表示是否对 HTML 特殊字符进行转义
读取规则
读取 ObjectStack 里的对象的属性,ObjectStack 里的对象可以通过一个从零开始的下标来引用,即可以使用[0].userName 来返回栈顶对象的 message 属性,结合 <s:property> 标签
若在指定的对象中没有找到指定的属性,则到指定对象的下一个对象里继续搜索,即 [n] 的意义是从第 n 个开始搜索,而不是只搜索第 n 个
若从栈顶对象开始搜索则可以省略下标
默认情况下 Action 对象会被 Struts2 自动的放到值栈的栈顶
// 如下两种写法都是从栈顶开始在对象栈中查找 key 为 userName 的属性
<s:property value="userName"/>
<s:property value="[0].userName"/>
Struts2 之值栈的更多相关文章
- struts2(二)值栈 threadlocal ogal ui
值栈(重要)和ognl表达式 1. 只要是一个mvc框架,必须解决数据的存和取的问题 2. Struts2利用值栈来存数据,所以值栈是一个存储数据的内存结构 3. 把数据存在值栈中,在页面上利用 ...
- Struts2的值栈和OGNL牛逼啊
Struts2的值栈和OGNL牛逼啊 一 值栈简介: 值栈是对应每个请求对象的一套内存数据的封装,Struts2会给每个请求创建一个新的值栈,值栈能够线程安全的为每个请求提供公共的数据存取服务. 二 ...
- 【Java EE 学习 36】【struts2】【struts2系统验证】【struts2 ognl值栈】【struts2 ongl标签】【struts2 UI标签】【struts2模型驱动和令牌机制】
一.struts2系统验证 1.基于struts2系统验证的方式实际上就是通过配置xml文件的方式达到验证的目的. 2.实际上系统校验的方法和手工校验的方法在底层的基本实现是相同的.但是使用系统校验的 ...
- Struts2向值栈中压入属性的方式
Struts2在初始化Action的时候会先向值栈中压入一个action对象,里面包含了各个属性,这些属性是怎么被压进去的?或者说是根据什么来压入的?直到2016年5月5日才理解,原来是在初始化act ...
- Struts2 的 值栈和ActionContext
1.ValueStack 和 ActionContext 的关系与区别: -- 相同点:它们都是在一次HTTP请求的范围内使用的,它们的生命周期都是一次请求 -- 不同点:ValueStack 分为对 ...
- Struts2的值栈和对象栈
ValueStack 如何得到值栈: 如何将对象存入值栈: 让值栈执行表达式来获得值: 在JSP中跳过栈顶元素直接访问第二层: 在JSP中访问值栈对象本身(而不是它们的属性) ActionContex ...
- 【struts2】值栈(后篇)
在值栈(前篇)我们学习了值栈的基本知识,接下来,来看看在程序中具体如何使用值栈. 1 ActionContext的基本使用 1.1 如何获取? 要获取ActionContext有两个基本的方法,如果在 ...
- 【struts2】值栈(前篇)
1 值栈是什么? 简单的说:值栈是对应每一个请求对象的轻量级的内存数据中心. Struts2中一个很激动人心的特性就是引入了值栈,在这里统一管理着数据,供Action.Result.Intercept ...
- struts2框架值栈的概述之问题一:什么是值栈?
1. 问题一:什么是值栈? * 值栈就相当于Struts2框架的数据的中转站,向值栈存入一些数据.从值栈中获取到数据. * ValueStack 是 struts2 提供一个接口,实现类 OgnlVa ...
随机推荐
- Bond UVA - 11354(LCA应用题)
Once again, James Bond is on his way to saving the world. Bond's latest mission requires him to trav ...
- WordPress禁止版本修订历史、自动保存和自动草稿最新方法汇总
提醒:我这里汇总的方法有一些只支持以前老版本的WordPress,对于新版本的WordPress,有些功能是不支持的,所以操作前请做好备份.我的WordPress版本目前是4.3.1,我会在我测试有效 ...
- 快速创建 HTML5 Canvas 电信网络拓扑图
前言 属性列表想必大家都不会陌生,正常用 HTML5 来做的属性列表大概就是用下拉菜单之类的,而且很多情况下,下拉列表还不够好看,怎么办?我试着用 HT for Web 来实现属性栏点击按钮弹出多功能 ...
- JDBC控制事务
概念 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit).事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并 ...
- Java日志框架:slf4j作用及其实现原理
简单回顾门面模式 slf4j是门面模式的典型应用,因此在讲slf4j前,我们先简单回顾一下门面模式, 门面模式,其核心为外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用.用一 ...
- 笔记:Spring Boot 监控与管理
在微服务架构中,我们将原本庞大的单体系统拆分为多个提供不同服务的应用,虽然,各个应用的内部逻辑因分解而简化,但由于部署的应用数量成倍增长,使得系统的维护复杂度大大提升,为了让运维系统能够获取各个为服务 ...
- 【Java】 重拾Java入门
[概论与基本语法] 取这个标题,还是感觉有些大言不惭.之前大三的时候自学过一些基本的java知识,大概到了能独立写一个GUI出来的水平把,不过后来随着有了其他目标,就把这块放下了.之后常年没有用,早就 ...
- 【Linux】 升级CentOS6的内核到3.10
升级内核 最近有一些虚拟机,想装Dokcer,但是实验之后发现Docker基本上只在3.0以上的linux内核版本中才能稳定运行.所以就面临着把CentOS6的2.6内核升级到3.0以上.下面提供两种 ...
- Android学习笔记1——开发环境配置
一.JDK配置 Android是基于Java进行开发的,首先需要在电脑上配置JDK(Java Development Kit).在http://www.androiddevtools.cn/下载对应系 ...
- redis的主从复制(读写分离)/哨兵(主从切换)配置
准备两个redis服务,两台机器,依次命名文件夹子master,slave1 10.10.10.7 10.10.10.8 1.master修改配置文件 [root@db2 conf]# cat 637 ...