值栈(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 之值栈的更多相关文章

  1. struts2(二)值栈 threadlocal ogal ui

    值栈(重要)和ognl表达式 1.  只要是一个mvc框架,必须解决数据的存和取的问题 2.  Struts2利用值栈来存数据,所以值栈是一个存储数据的内存结构 3.  把数据存在值栈中,在页面上利用 ...

  2. Struts2的值栈和OGNL牛逼啊

    Struts2的值栈和OGNL牛逼啊 一 值栈简介: 值栈是对应每个请求对象的一套内存数据的封装,Struts2会给每个请求创建一个新的值栈,值栈能够线程安全的为每个请求提供公共的数据存取服务. 二 ...

  3. 【Java EE 学习 36】【struts2】【struts2系统验证】【struts2 ognl值栈】【struts2 ongl标签】【struts2 UI标签】【struts2模型驱动和令牌机制】

    一.struts2系统验证 1.基于struts2系统验证的方式实际上就是通过配置xml文件的方式达到验证的目的. 2.实际上系统校验的方法和手工校验的方法在底层的基本实现是相同的.但是使用系统校验的 ...

  4. Struts2向值栈中压入属性的方式

    Struts2在初始化Action的时候会先向值栈中压入一个action对象,里面包含了各个属性,这些属性是怎么被压进去的?或者说是根据什么来压入的?直到2016年5月5日才理解,原来是在初始化act ...

  5. Struts2 的 值栈和ActionContext

    1.ValueStack 和 ActionContext 的关系与区别: -- 相同点:它们都是在一次HTTP请求的范围内使用的,它们的生命周期都是一次请求 -- 不同点:ValueStack 分为对 ...

  6. Struts2的值栈和对象栈

    ValueStack 如何得到值栈: 如何将对象存入值栈: 让值栈执行表达式来获得值: 在JSP中跳过栈顶元素直接访问第二层: 在JSP中访问值栈对象本身(而不是它们的属性) ActionContex ...

  7. 【struts2】值栈(后篇)

    在值栈(前篇)我们学习了值栈的基本知识,接下来,来看看在程序中具体如何使用值栈. 1 ActionContext的基本使用 1.1 如何获取? 要获取ActionContext有两个基本的方法,如果在 ...

  8. 【struts2】值栈(前篇)

    1 值栈是什么? 简单的说:值栈是对应每一个请求对象的轻量级的内存数据中心. Struts2中一个很激动人心的特性就是引入了值栈,在这里统一管理着数据,供Action.Result.Intercept ...

  9. struts2框架值栈的概述之问题一:什么是值栈?

    1. 问题一:什么是值栈? * 值栈就相当于Struts2框架的数据的中转站,向值栈存入一些数据.从值栈中获取到数据. * ValueStack 是 struts2 提供一个接口,实现类 OgnlVa ...

随机推荐

  1. this->的作用

    参考:https://www.zhihu.com/question/23324143 1.来源: 当年没有C++编译器,只能通过C++转成C语言才编译.而C++中的class就被翻译C语言的struc ...

  2. 基于Avocado 的 QData MySQL自动化测试.md

    qdata-mysql 自动化测试概要设计 │   ├── 1. 依赖环境 │   │   ├ │   │   └───── │   ├── 2. 配置文件 │   │   ├ │   │   └── ...

  3. sshpass的使用方法

    author:headsen  chen date : 2017-11-29  15:46:39 notice:created  by  headsen chen himself   and not ...

  4. 开源自己用python封装的一个Windows GUI(UI Automation)自动化工具,支持MFC,Windows Forms,WPF,Metro,Qt

    首先,大家可以看下这个链接 Windows GUI自动化测试技术的比较和展望 . 这篇文章介绍了Windows中GUI自动化的三种技术:Windows API, MSAA - Microsoft Ac ...

  5. TortoiseGit- 创建本地新分支,提交推送到远程,本地新分支合并到工作分支,提交到远程工作分支等。

    整体思路: 创建本地新分支 (create branch)  -- 切换到本地新分支工作 (switch/checkout) --提交修改 (commit)  -- 推送到远程新分支 (push)  ...

  6. xampp配置多端口访问

    1.修改D:\xampp\apache\conf\extra中的httpd-vhosts.conf文件,在最底部添加 <VirtualHost *:8080> ##需要监听的端口号 Ser ...

  7. push_back和emplace_back的区别

    emplace_back能就地通过参数构造对象,不需要拷贝或者移动内存,相比push_back能更好地避免内存的拷贝与移动,使容器插入元素的性能得到进一步提升.在大多数情况下应该优先使用emplace ...

  8. 通过漫画轻松掌握HDFS工作原理

  9. 自动化运维工具---expec

    作为运维经常操作Linux服务器是不可避免的事情的,那么你们都是怎么管理的呢? 我们管理的方式较为复杂了,我说一下: 有一套服务器资产管理系统,所有服务器都记录在上面,包括用户名密码,内外网地址都会有 ...

  10. 单例模式双重检验锁的判断是否为null的意义

    关于双重检验锁首先简单来看一个小例子: public class Singleton{ private static Singleton instance = null; private Single ...