Struts2值栈详解
基本介绍
ValueStack是Struts2的一个接口,字面意义为值栈,OgnlValueStack是 ValueStack的实现类,客 户端发起一个请求,struts2架构会创建一个action实例同时创建一个OgnlValueStack值栈实例, OgnlValueStack贯穿整个Action的生命周期,struts2中使用OGNL将请求Action的参数封装为对象存储 到值栈中,并通过OGNL表达式读取值栈中的对象属性值。
PS:这里先说明一个易混淆的问题,那就是ContextMap和值栈的关系,从广义上来讲,ContextMap中存入了一个值栈的键值对。值栈中又有一个ContextMap的引用,这样就形成了一个互相引用的关系。所以说从广义上来讲,无论是从ContextMap的角度来分析,还是从StackValue的角度来分析,都没问题。有很多文档是以StackValue为起点,逐步分析到ContextMap。不过官方文档,还是以ContextMap作为起点。
值栈的内部结构
OnglValueStack源码
public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {CompoundRoot root;transient Map<String, Object> context;
}
CompoundRoot源码
public class CompoundRoot extends ArrayList {public CompoundRoot() {}public CompoundRoot(List list) {super(list);}public CompoundRoot cutStack(int index) {return new CompoundRoot(subList(index, size()));}public Object peek() {return get(0);}public Object pop() {return remove(0);}public void push(Object o) {add(0, o);}
}
由以上源码可以看出,OnglValueStack有两部分,一部分是继承ArrayList实现的一个栈结构,一个就是之前介绍过的,在《ContextMap详解》中介绍过的ContextMap。
关于ContextMap的介绍,这里不再给出,可以参考之前的博客《ContextMap详解》,这里分析下栈结构,也就是CompoundRoot,也就是OGNL三大要素之一的根对象(root),可以参考《ONGL基本使用 》。
CompoundRoot
  • CompoundRoot:存储了action实例,它作为OgnlContext的Root对象。
CompoundRoot继承ArrayList 实现压栈和出栈功能,拥有栈的特点,先进后出,后进先出,最后压进栈的数据在栈顶。
struts2对原OGNL作出的改进就是Root使用CompoundRoot(自定义栈),使用OnglValueStack
的findValue方法可以在CompoundRoot中从栈顶向栈底查找对象的属性值。
CompoundRoot作为OgnlContext的Root对象,并且在CompoundRoot中action实例位于栈顶, 当读取achon的属性值时会先从栈顶对象中查找对应的属性,如果找不到则继续查找栈中的其它对象, 如果未找到则到ContextMap中去查找,未找到,则返回null。     
案例
package com.pc.web.action;import com.itheima.domain.Student;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;/*** ValueStack存值取值操作* @author Switch* 当我们不操作值栈时,默认的栈顶对象是:当前执行的动作类*/
public class ActionTest2 extends ActionSupport {private String name="泰斯特";/*** @return*/public String demo2(){//1.获取ActionContext//从当前线程上获取ActionContext context = ActionContext.getContext();//2.使用ActionContext中的方法获取ValueStack//context.get(ValueStack.VALUE_STACK)//context.get("com.opensymphony.xwork2.util.ValueStack.ValueStack");// //也可以通过request域获取值栈//ServletActionContext.getRequest().getAttribute("struts.valueStack");ValueStack vs = context.getValueStack();//3.压栈操作:把一个学生对象压入栈顶Student s = new Student();s.setName("switch");s.setAge(20);//压栈操作vs.push(s);return SUCCESS;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
<%@page import="com.opensymphony.xwork2.util.ValueStack"%>
<%@page import="com.opensymphony.xwork2.ActionContext"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!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>ValueStack的操作</title>
</head>
<body>
<%--1、取出ValueStack中第一个name属性的值
借助s:property标签来获取。
取值栈中的数据:直接写属性名称,获取的就是属性值。不需要使用#号。
OGNL表达式在获取值栈数据时,默认情况下都是从栈顶逐个对象往下寻找,寻找属性一致的,把属性值取出来。
只要找到之后,就不再继续寻找。OGNL表达式获取值栈中的数据,只能是根据属性名称获取属性值。
--%>
Name:<s:property value="name"/><br/>
Age:<s:property value="age"/>
<hr/>
<%--2、获取指定位置属性值使用的OGNL表达式是:[x].namex指的是值栈中对象的索引位置。
--%>
Name1:<s:property value="[0].name"/><br/>
Name2:<s:property value="[1].name"/><br/>
<hr/>
<%--3、当我们使用s:property标签时,没有使用value属性,获取的是栈顶对象。当我们不操作值栈时,默认的栈顶对象是:当前执行的动作类--%>
<s:property/>
<hr/>
<%--4、OGNL表达式在OGNL上下文中查找数据时涉及的方法不管是在Map中找,还是在值栈中找,对应的方法只有一个。ValueStack的对象中的findValue(String expr)方法。参数的含义:是一个OGNL表达式--%><% ActionContext context = ActionContext.getContext();ValueStack vs = context.getValueStack();Object o1 = vs.findValue("name");out.println("name is "+o1);out.println("<br/>");Object o2 = vs.findValue("[1].name");out.println("name1 is "+o2);out.println("<br/>");Object o3 = vs.findValue("#session.sessionMap3");out.println(o3);out.println("<br/>");Object o4 = vs.findValue("#application.applicationAttr");out.println(o4);%>
<s:debug></s:debug>
</body>
</html>
OgnlValueStack中push和set的区别
public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {CompoundRoot root;public void push(Object o) {root.push(o);}public void set(String key, Object o) {//set basically is backed by a Map pushed on the stack with a key being put on the map and the Object being the valueMap setMap = retrieveSetMap();setMap.put(key, o);}private Map retrieveSetMap() {Map setMap;Object topObj = peek();if (shouldUseOldMap(topObj)) {setMap = (Map) topObj;} else {setMap = new HashMap();setMap.put(MAP_IDENTIFIER_KEY, "");push(setMap);}return setMap;}public Object peek() {return root.peek();}private boolean shouldUseOldMap(Object topObj) {return topObj instanceof Map && ((Map) topObj).get(MAP_IDENTIFIER_KEY) != null;}
}
PS:通过源码可以看出,push直接将对象压入CompoundRoot中,set如果第一次使用,会创建一个map对象,并将键值对设置进去,如果不是第一次,则会将键值对直接放入该map中。

Struts2值栈详解相关推荐

  1. struts2值栈内部数据结构详解

    值栈是struts2内部一片很重要的区域,我在初学的时候,发现对于值栈这个数据结构的理解不是很深刻.例如OGNLContext是什么,ActionContext和值栈有什么关系.为什么ActionCo ...

  2. 数据结构-链栈详解(很朴实的那种)

    链栈的设计与运行 1.链栈 提起链栈,很容易就想到单链表,不过链栈确实可以看做是受限的单链表,因为只能在链表头部进行操作,所以在链栈中也不再附加头结点,栈顶指针就是链表的头指针. 老话一句,实践一遍, ...

  3. python列表切片后得到剩余列表_python列表切片和嵌套列表取值操作详解

    python列表切片和嵌套列表取值操作详解 给出列表切片的格式: [开头元素::步长] # 输出直到最后一个元素,(最后一个冒号和步长可以省略,下同) [开头元素:结尾元素(不含):步长] # 其中, ...

  4. ceph存储原理_赠书 | Linux 开源存储全栈详解——从Ceph到容器存储

    // 留言点赞赠书我有书,你有故事么?留言说出你的存储故事留言点赞前两名,免费送此书截止日期12.27号12.30号公布名单 // 内容简介 本书致力于帮助读者形成有关Linux开源存储世界的细致的拓 ...

  5. openstack架构详解图_英特尔顶级技术专家合力缔造精品:Linux开源网络全栈详解...

    日常水开篇 自1991年诞生起,Linux已经走过了接近三十年.Linux早已没有了问世时的稚气,正在各个领域展示自己成熟的魅力. 以Linux为基础,也衍生出了各种开源生态,例如网络和存储.而生态离 ...

  6. python修改xml标签的值_对python修改xml文件的节点值方法详解

    这是我的xml文件结构 <?xml version='1.0' encoding='utf-8'?> JPEGImages train_2018-05-08_1000.jpg D:\all ...

  7. (十)Struts2 值栈/OGNL

    值栈是一组对象,按照提供的顺序存储以下这些对象: 序号 对象和说明 1 Temporary对象 实际中存在各种在页面执行期间创建的temporary对象.例如,JSP标签循环集合的当前迭代值. 2 M ...

  8. (转)C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

    原文链接:https://www.cnblogs.com/landeanfen/p/5501487.html 阅读目录 一.void无返回值 二.IHttpActionResult 1.Json(T ...

  9. struts2值栈、struts2标签、ONGL表达式、EL表达式、JSTL表达式、jsp标签

    1.struts2值栈: 参考:https://blog.csdn.net/superit401/article/details/83994149 (1) ValueStack是Struts2的一个接 ...

最新文章

  1. linux watch命令
  2. Python format 格式化函数
  3. JS如何从数组中随机取出若干个数,且不重复
  4. 配置Exchange 2010 服务器(二)Exchange2010证书配置
  5. android--------WebView 实现缓存网页数据
  6. 使用go来实现类似erlang otp里面的gen_server功能
  7. linux : 各个发行版中修改python27默认编码为utf-8
  8. NTV Media Server G3性能测试
  9. 圆弧裁剪算法c++_程序媛转TA之理论篇十二:反走样的几种算法原理
  10. 如何自动加载scratch3.0的页面上实现自动加载原有的作品
  11. java 网站计数器_网站计数器——Java实现
  12. 关系型数据库管理系统
  13. Debian回收站无法删除解决
  14. Running Median
  15. 简单说一下http的优点和缺点?
  16. c语言处理nc程序,NC程序的语言问题
  17. 【奥特曼迪迦表情包】
  18. win10计算机属性管理打不开,win10系统此电脑属性打不开怎么办
  19. WebRTC学习笔记七 pion/webrtc
  20. 资深美女基金经理首次分享基金知识,好评如潮!!!

热门文章

  1. [0].Net开发者社区--您好大的官威啊!
  2. 【JAVA 第四章 流程控制语句】课后习题 冒泡排序的运用
  3. 机器学习相关的一些术语
  4. 很想去的地方面试没过_我们研究了学生在技术面试中的表现。 他们上学的地方没关系。...
  5. Java toBinaryString()函数探究及Math.abs(-2147483648)=-2147483648原理探究
  6. 复习django项目一——迁移数据库
  7. php函数巧用 array_column
  8. linux系统修改为静态IP地址
  9. 一日一技:一文搞懂Python错误和异常
  10. 虚拟语气和推测(三)