7.1值栈

7.1.1值栈是什么

简单的说:值栈是对应每一个请求对象的轻量级的内存数据中心。

Struts2中一个很激动人心的特性就是引入了值栈,在这里统一管理着数据,供Action、Result、Interceptor等Struts2的其他部分使用,这样一来,数据被集中管理起来而不会凌乱,大大方便了程序编写。

Struts2中关于值栈的另外一个很激动人心的特性就是:大多数情况下,你根本无需关心值栈,你不用管它在哪里,不用管它里面有什么,你只需要去获取自己需要的数据就可以了。也就是说,你可以隐式的使用值栈。

当然,如果编写自定义的Result或拦截器等较复杂功能的时候,还是需要显示访问值栈的,因此,还是需要你掌握值栈的知识。

7.1.2值栈能干什么

简单的说,值栈能够线程安全的为每个请求提供公共的数据存取服务。

当有请求到达的时候,Struts2会为每个请求创建一个新的值栈,也就是说,值栈和请求是一一对应的,不同的请求,值栈也不一样,而值栈封装了一次请求所有需要操作的相关的数据。

正是因为值栈和请求的对应关系,因而值栈能保证线程安全的为每个请求提供公共的数据存取服务。

7.1.3值栈有什么

事实上,到现在为止,我们一直在讲“值栈”,这种说法其实是不够准确的。为什么呢?因为在Struts2中,值栈又有广义和狭义之分:

1:狭义值栈

通常指的是实现com.opensymphony.xwork2.util.ValueStack接口的对象,目前就是com.opensymphony.xwork2.ognl.OgnlValueStack对象。

狭义值栈主要用来存取动态EL(表达式语言)运算需要的值和结果,当然OgnlValueStack对象主要是用来支持OGNL(对象图导航语言)运算的。

狭义值栈里面存放着一些OGNL可以存取访问的数据,典型如:Action的实例,这样就可以通过OGNL来访问Action实例中的属性的值了

OGNL表达式运算的值,可以设置到值栈中,可以主动访问值栈对象,强行设置

OGNL表达式产生的中间变量,比如在后面使用Struts2的标签的时候,使用循环标签,自然会有循环的变量,这些都存放在值栈中

2:广义值栈

通常指的是ActionContext对象,ActionContext是Action运行的上下文,每个ActionContext是一个基本的容器,包含着Action运行需要的数据,比如请求参数、会话等。

ActionContext是线程安全的,每个线程有一个独立的ActionContext,这样你就不用担心值栈中值的线程安全问题了。

ActionContext里面存放有很多的值,典型如:Request的parameters:请求中的参数,要注意这里的数据是从请求对象里面拷贝出来的,因此这里数据的变化是不会影响到请求对象里面的参数的值的

Request的Attribute:请求中的属性,这里其实就是个Map,存放着请求对象的属性数据,这些数据和请求对象的Attribute是连动的

Session的Attribute:会话中的属性,这里其实就是个Map,存放着会话对象的属性数据,这些数据和会话对象的Attribute是连动的

Application的Attribute:应用中的属性,这里其实就是个Map,存放着应用对象的属性数据,这些数据和应用对象的Attribute是连动的

Value stack:也就是狭义值栈,ActionContext以value stack作为被OGNL访问的根,简单点说,OGNL在没有特别指明的情况下,访问的就是value stack里面的数据

attr:在所有的属性范围中获取值,依次搜索page、request、session和application。

前面已经了解到Xwork与Web是无关的,因此Action不用去依赖于任何Web容器,不用和Servlet 的API去交互,但是Action需要能访问到Web应用的数据,不仅仅是取得请求参数的值,往往也需要在Action里直接获取请求或会话的一些数据,对于这些数据,现在都可以通过ActionContext来获取到。

3:关于广义和狭义

你会看到,在ActionContext里面其实是包含着狭义值栈的,正是因为这个原因,再加上ActionContext还包含其他的数据,因此把ActionContext称为广义值栈。

今后在说值栈的时候,没有特别指明的情况下,多数就是指的广义值栈,反正开发的时候都是说从值栈中获取值。当然,有一种情况除外,就是在页面上使用OGNL的时候,没有特殊标识的情况下,默认是从value statck中取值的。

7.1.4ActionContext的基本使用

前面学习了值栈的基本知识,接下来,看看在程序中具体如何使用值栈。

1:如何获取

要获取ActionContext有两个基本的方法,如果在不能获取到ActionInvocation的地方,可以直接使用ActionContext一个静态的getContext方法,就可以访问到当前的ActionContext了,示例如下:

java代码:

ActionContext ctx = ActionContext.getContext();

如果在能获取到ActionInvocation的地方,比如在拦截器里面、自定义的Result里面等,可以通过ActionInvocation来获取到ActionContext,示例如下:

java代码:

ActionContext ctx = actionInvocation.getInvocationContext();

2:获取过后,如何使用

ActionContext主要的功能是用来存放数据的,典型的方法如下:get(String key):根据key从ActionContext当前的存储空间里面获取相应的值

put(String key, Object value):把值存储在ActionContext的存储空间里面

Map getApplication():返回ServletContext中存储的值

Map getSession():返回HttpSession中存储的值

Map getContextMap():返回当前context存储的值

Map getParameters():返回HttpServletRequest对象里面存储的,客户端提交的参数

ValueStack getValueStack():获取OGNL的值栈

对于getXXX的方法,都有对应的setXXX方法,这里就不去赘述了,具体的请参看Struts2的API文档。

3:应用示例

可以参看上一章的两个有用的拦截器这一小节,两个拦截器都使用了ActionContext对象,因此这里就不去赘述了。

7.1.5ValueStack的基本使用

在上一小节中,看到了ValueStack被包含在ActionContext中,ValueStack也是用来存储对象的,但是它主要是通过OGNL表达式来访问,也就是说,在Struts2里面主要是通过标签来访问的。

ValueStack有一个特点,如果访问的值栈里有多个对象,且相同的属性在多个对象中同时出现,则值栈会按照从栈顶到栈底的顺序,寻找第一个匹配的对象。

1:如何获取

直接由ActionContext对象的getValueStack()方法即可获取

2:如何使用

ValueStack主要的功能也是用来存放数据的,典型的方法如下:Object findValue(String expr):根据表达式在value stack中,按照缺省的访问顺序去获取表达式对应的值

void setValue(String expr, Object value):根据表达式,按照缺省的访问顺序,向value stack中设置值

Object peek():获取value stack中的顶层对象,不修改value stack对象

Object pop():获取value stack中的顶层对象,并把这个对象从value stack中移走

void push(Object o):把对象加入到value stack对象中,并设置成为顶层对象

3:应用示例

前面的示例中,欢迎页面显示的帐号,是从登录页面填写并传递到后台的数据,假如现在想要修改在欢迎页面显示的帐号数据,但是前面从登录页面填写并传递到后台的数据不需要变化,那么该怎么实现呢?

先来分析一下,要想修改result页面显示的值,肯定需要在Result处理之前修改这个值,否则等Result处理完成过后再改就没有意义了。因此,可以选用PreResultListener的技术,在里面把值修改好,然后再进行Result处理。

另外一点,在欢迎页面是通过标签来获取帐号的数据并展示的,也就是说值的来源是value stack,因此,在PreResultListener里面要修改的就是value stack里面的值。

好了,清楚该干什么过后,来具体看看示例。

(1)先来实现PreResultListener,在里面修改value stack里面的值,示例如下:

java代码:

publicclassMyPreResultimplementsPreResultListener{

publicvoidbeforeResult(ActionInvocation actionInvocation, String result) {

System.out.println("现在处理Result执行前的功能,result="+result);

actionInvocation.getInvocationContext().getValueStack().setValue("account","被修改了");

}

}

(2)实现了PreResultListener,还需要在运行之前注册,这里选择在Action里面来注册这个监听器,示例如下:

java代码:

publicclassHelloWorldActionextendsActionSupport {

privateString account;

privateString password;

privateString submitFlag;

publicString execute()throwsException {

this.businessExecute();

ActionContext c = ActionContext.getContext();

MyPreResult pr = newMyPreResult();

c.getActionInvocation().addPreResultListener(pr);

return"toWelcome";

}

/**

* 示例方法,表示可以执行业务逻辑处理的方法,

*/

publicvoidbusinessExecute(){

System.out.println("用户输入的参数为==="+"account="+account+",password="+password+",submitFlag="+submitFlag);

}

//属性对应的getter/setter方法,省略了

}

(3)相应的struts.xml就比较简单了,示例如下:

java代码:

/s2impl/welcome.jsp

(4)登录页面没有变动,示例如下:

java代码:

账号:

密码:

(5)再看看欢迎页面,也没有变动,示例如下:

java代码:

欢迎账号为的朋友来访

(6)去运行测试看看,欢迎页面显示出来的就应该是修改过后的值了,如下图所示:

图7.1  修改result数据的欢迎页面

由于通常情况下,向value stack里面压入值都是由Struts2去完成,而访问value stack多是通过标签中的OGNL表达式,因而直接使用ValueStack的机会并不是很多。

java值栈_Struts2 中的值栈是什么?相关推荐

  1. selenium+java:获取列表中的值

    selenium+java:获取列表中的值 (2011-08-23 17:14:48) 标签: 杂谈 分类: selenium 初步研究利用java+testNg框架下写selenium测试用例,今天 ...

  2. 父进程中getpid()值与子进程中getppid()值不相同的问题及解释

    父进程中getpid()值与子进程中getppid()值不相同的问题及解释 使用fork()创建一个新的子进程,并调用getpid()与getppid()查看父子进程之间的pid的关系.示例代码如下: ...

  3. java中有没有栈_Java中堆和栈有什么区别

    stack 和 heep 都是内存的一部分stack 空间小,速度比较快, 用来放对象的引用heep 大,一般所有创建的对象都放在这里.栈(stack):是一个先进后出的数据结构,通常用于保存方法(函 ...

  4. java内存堆和栈_java中堆,栈主要区别及内存存储

    java堆.栈.堆栈的区别 1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取速度 ...

  5. java静态方法 问题_Java中堆、栈,静态方法和非静态方法的速度问题

    一.堆和栈的速度性能分析 堆和栈是JVM内存模型中的2个重要组成部分,自己很早以前也总结过堆和栈的区别,基本都是从存储内容,存储空间大小,存储速度这几个方面来理解的,但是关于堆和栈的存储速度,只知道堆 ...

  6. java中random方法取值范围_java中最值的求法,你可能忽略了这种方法了!

    对一批数据进行排序,然后找出其中的最大值或最小值,这是基本的数据结构知识.在Java中我们可以通过编写算法的方式,也可以通过数组先排序再取值的方式来实现.下面以求最大值为例,解释一下多种算法. 自行实 ...

  7. python什么是堆什么是栈_python中堆和栈_Python小知识00002

    原博文 2019-05-15 09:48 − 变量位于栈 对象位于堆 ... 0 739 相关推荐 2019-12-03 17:11 − 目录 Python 全栈之路 一. Python 1. Pyt ...

  8. python字典取值_python 字典中取值的两种方法小结

    python 字典中取值的两种方法小结 如下所示: a={'name':'tony','sex':'male'} 获得name的值的方式有两种 print a['name'],type(a['name ...

  9. php如何移除数组中的某个值,删除数组中某个值元素_PHP教程

    删除数组中某个值元素本实例是要利用php array_diff函数来,删除数组中某个值元素哦,方法很简单用foreach再加array_diff函数就 删除数组中某个值元素 本实例是要利用php教程 ...

最新文章

  1. Ubuntu下Sublime Text 3解决无法输入中文的方法
  2. NLP 注意力机制总结言简意赅的
  3. php 表单错误弹窗,PHP表单错误
  4. LFS-构建自己的linux
  5. 【单片机实验】矩阵键盘
  6. zanli_android_1.1.0,【轻松集赞】写了个涉嫌混淆微信官方服务的小程序
  7. Java 数组中new Object[5]语句是否创建了5个对象?
  8. 项目 协程-实现非抢占式TCP服务器
  9. PolkaFoundry等成立Polkadot区块链开发协会(PBDA)
  10. 【高薪、俱进、携手】只要你敢来,海云就敢要!
  11. HyperLPR车牌识别代码解读
  12. mongoDB清空数据库
  13. 计算机科学与技术专业课程简介
  14. 拍照时怎样摆姿势好看?
  15. 苹果手机微信端打开网页长按保存图片可以唤醒但是点击保存、发好友无效
  16. UE4 快捷键--引擎篇
  17. java 混淆war,java yguard混淆web工程
  18. 关于logrotate的使用
  19. DDoS 攻击的趋势
  20. 智慧停车成为了改善停车环境、满足停车需求的“香饽饽”

热门文章

  1. ie浏览器网页版进入_Win10系统中IE和edge浏览器无法打开网页如何解决
  2. jaccard相似度_如何计算两个字符串之间的文本相似度?
  3. 请解释自动装配模式的区别?_如何从齿条优化方面有效节约机床装配时间
  4. php ajax json 实例,php+ajax+json 详解及实例代码
  5. 宝塔php漏洞,[安全预警]关于最近宝塔闹得很厉害的PMA漏洞BUG
  6. Win11任务栏图标重叠怎么办 Win11任务栏图标重叠的解决方法
  7. div+css 单行或者多行超出文本,数字,字母长度自动省略
  8. Java:File.separator作用相当于 ‘ \ ‘
  9. Java并发——线程安全
  10. 学习Spring Boot:(二十六)使用 RabbitMQ 消息队列