值栈(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. 平衡树(Splay)模板

    支持区间操作. 单点操作和区间操作分开使用,需要一起使用需要部分修改. 对应题目FJUTOJ2490 #include<cstdio> #include<cstring> #i ...

  2. assert断言检测

    assert 是宏,非函数,包含在assert.h 头文件中. 如果其后面括号里的值为假,则程序终止运行,并提示出错.这个 宏只在 Debug 版本上起作用,而在 Release 版本被编译器完全优化 ...

  3. Java反射总结

    一. 获取Class对象的3种方法: 1. Class.forName("");例如:Class.forName("java.lang.String"); 2. ...

  4. OSI七层模型对应的协议

    osi七层模型对应的协议 author:headsen chen    2017-10-21  11:44:47 个人原创,转载请注明作者,出处.否则依法追究法律责任 1,物理层:带信号的,同轴电缆, ...

  5. Atlas安装配置

    准备环境 192.168.1.1(Altas) 192.168.1.2(MySQL主) 192.168.1.3(MySQL从) 官方链接:https://github.com/Qihoo360/Atl ...

  6. JS中原始值和引用值的储存方式

    在ECMAscript中,变量可以存放两种类型的值,即原始值和引用值 原始值指的是代表原始数据类型的值,也叫基本数据类型,包括:Number.Stirng.Boolean.Null.Underfine ...

  7. python函数名称空间

    一.命名空间概念 命名空间(name space),若变量x=1,1存放在内存中,命名空间是存放名字x.x与1绑定关系的地方.命名空间分三种: locals:函数内的名称空间,包括局部变量和形参 gl ...

  8. spy++捕获窗口消息

    打开spy++,窗口截图如下,点击窗口搜索按钮(红框标识) ,如果找不到对应的窗口,鼠标右键刷新即可. 鼠标左键点击窗口搜索图标,按住不放,拖到需要抓取消息的窗口上: spy++会自动在列表中高亮定位 ...

  9. [机器学习Lesson 1 Introduction] 机器学习的动机与应用

    1. Machine Learning definition(机器学习定义) Arthur Samuel(1959年)将机器学习非正式定义为:在不直接针对问题进行编程的情况下,赋予计算机学习能力的一个 ...

  10. 基于 IJKPlayer-concat 协议的视频无缝拼接技术实现

    一.前言 Hi,大家好,我是承香墨影! 开门见山,开篇名义.今天来聊聊如何将多段视频,拼接成一个完整而连续的视频,然后无缝进行播放. 这样的需求应该不算偏门吧? 最简单的就是一些视频 App,会将大段 ...