Struts2之ValueStack、ActionContext
今天在看Action获取Resquest、Response时,发现了一个词:值栈。于是今天一天都在看,了解了值栈不仅能知道Action怎么获取request、response等这些,还会了解OGNL语言的工作原理。在网上找了下,有一个帖子总结的挺好,所以先提前声明一下,我这篇主要参考是:https://my.oschina.net/u/1425737/blog/197939.
一、ActionContext
ActionContext是Action的上下文,Struts2自动在其中保存了一些在Action执行过程中所需的对象,比如session, parameters, locale等。Struts2会根据每个执行HTTP请求的线程来创建对应的ActionContext,即一个线程有一个唯一的ActionContext。因此,使用者可以使用静态方法ActionContext.getContext()来获取当前线程的ActionContext,也正是由于这个原因,使用者不用去操心让Action是线程安全的。
无论如何,ActionContext都是用来存放数据的。Struts2本身会在其中放入不少数据,而使用者也可以放入自己想要的数据。ActionContext本身的数据结构是映射结构,即一个Map,用key来映射value。所以使用者完全可以像使用Map一样来使用它,或者直接使用Action.getContextMap()方法来对Map进行操作。
Struts2本身在其中放入的数据有ActionInvocation、application(即ServletContext)、conversionErrors、Locale、action的name、request的参数、HTTP的Session以及值栈等。完整的列表请参考它的Javadoc(本文附录有对它包含内容的讨论)。
由于ActionContext的线程唯一和静态方法就能获得的特性,使得在非Action类中可以直接获得它,而不需要等待Action传入或注入。需要注意的是,它仅在由于request而创建的线程中有效(因为request时才创建对应的ActionContext),而在服务器启动的线程中(比如fliter的init方法)无效。由于在非Action类中访问其的方便性,ActionContext也可以用来在非Action类中向JSP传递数据(因为JSP也能很方便的访问它)。
1.如何获得ActionContext:
在自定义的拦截器中:使用ActionInvocation.getInvocationContext()或者使用ActionContext.getContext()。
在Action类中:让拦截器注入或者使用ActionContext.getContext()。
在非Action类中:让Action类传递参数、使用注入机制注入或者使用ActionContext.getContext()。注意:只有运行在request线程中的代码才能调用ActionContext.getContext(),否则返回的是null。
在JSP中:一般不需要获得ActionContext本身。
2.如何向ActionContext中存入值:
在拦截器、Action类、非Action类等Java类中:使用ActionContext.put(Object key, Object value)方法。
在JSP中:标签<s:set value="..."/>默认将值存入ActionContext中(当然,<s:set>标签还可以把值存到其他地方)。另外,许多标签都有var属性(以前用的是id属性,现在id属性已被弃用),这个属性能向ActionContext存入值,key为var属性的值,value为标签的value属性的值。
3.如何从ActionContext中读取值:
在拦截器、Action类、非Action类等Java类中:使用ActionContext.get(Object key)方法。
在JSP中:使用#开头的Ognl表达式,比如<s:property value="#name"/>会调用ActionContext.get("name")方法。注意:如果某标签的属性默认不作为Ognl表达式解析,则需要使用%{}把表达式括起来,于是就会出现类似“%{#name}的表达式”。(“#”的更多用途参见这里)
总之,在JSP中使用ActionContext一方面是由于它是映射结构,另一方面是能读取Action的一些配置。当你需要为许多Action提供通用的值的话,可以让每个Action都提供getXXX()方法,但更好的方法是在拦截器或JSP模板中把这些通用的值存放到ActionContext中(因为拦截器或JSP模板往往通用于多个Action)。
二、值栈ValueStack
其本身数据结构是一个栈,使用者可以把一些对象(又称作bean)存入值栈中,然后使用动态的表达式来读取bean的属性,或者对bean进行一些其他操作。由于值栈中可能有多个bean,值栈会按bean出栈的顺序依次尝试使用动态的表达式来读取值,直到成功读取值为止。在Struts2中,默认的值栈实现是OgnlValueStack,即默认使用Ognl这个动态表达式语言来读取值。
在Struts2执行一次请求的过程中,Struts2会把当前的Action对象自动放入值栈。这样,在渲染JSP时,JSP里的代码使用<s:property value="..."/>之类标签中的Ognl表达式会直接作用于Action对象,从而方便的读取Action的属性。
1.如何将对象存入值栈:
Struts2自动存入Action:之前已经提到,Struts2在执行一次请求的过程中会把当前的Action对象自动存入值栈中。
ModelDrivenInterceptor会存入Action的model属性:如果你使用了Struts2提供的 ModelDrivenInterceptor,则它会把Action对象的getModel()方法得到的对象存入值栈中。此时,值栈最底层为Action类,其次为这个model。
在自定义的拦截器中存入值栈:得到值栈对象后调用ValueStack.put(Object object)方法。
在Action类中存入值栈:得到值栈对象后调用ValueStack.put(Object object)方法。
在JSP中存入值栈:标签<s:push value="..."></s:push>是专门用来在JSP中把指定的value放入值栈的,但value被放入值栈的时间仅在s:push标签内,即程序运行到</s:push>标签处会把value从值栈中移出。另外,还有一些标签比如<s:iterator/>由于其功能的需要也会把一些对象放到值栈中。
2.让值栈执行表达式来获得值:
在自定义的拦截器中,获得值栈后,使用ValueStack.findValue(...)等方法。
在Action类中,获得值栈后,使用ValueStack.findVlaue(...)等方法。
在JSP中,一些标签的属性是直接在值栈上执行Ognl表达式的,比如<s:property/>的value属性。如果标签的属性不是直接执行Ognl表达式的,则需要使用“%{}”将表达式括起来,这样Struts2就会以Ognl表达式来执行了。至于到底哪些标签是直接执行Ognl而哪些不是,请参考完整的官方文档。
3.在JSP中跳过栈顶元素直接访问第二层:
在JSP中,使用[0]、[1]等表达式来指定从栈的第几层开始执行表达式。[0]表示从栈顶开始,[1]表示从栈的第二层开始。比如表达式“name”等价于“[0].name”。参见此处。
4.在JSP中访问值栈对象本身(而不是它们的属性)
在表示式中使用top关键字来访问对象本身。比如,表达式“name”等价于“top.name”,表达式“[0].top”等价于“top”,表达式“[1].top.name”等价于“[1].name”。
总之,值栈主要目的是为了让JSP内能方便的访问Action的属性。
三、值栈ValueStack和Action的区别与联系
相同点:它们都是在一次HTTP请求的范围内使用的,即它们的生命周期都是一次请求
值栈是栈的结构,ActionContext是映射(Map)的结构。
联系:ValueStack.getContext()方法得到的Map其实就是ActionContext的Map。在创建ActionContext时,就是把ValueStack.getContext()作为ActionContext的构造函数的参数。所以,ValueStack和ActionContext本质上可以互相获得。
四、HttpServletSession、ActionContext、ServletContext等获取方式
| 变量 | 从ActionContext中获得 | 生命周期 | 用Ongl来读取值 | 使用ServletConfigInterceptor来注入 |
| ActionContext类 | 静态方法ActionContext. getContext() | 一次Http请求 | 使用“#”加上key,如“#name” | 无法注入 |
| ValueStack类 | ActionContext. getValueStack() | 一次Http请求 | 直接填写来访问栈中对象的方法,或者使用top来直接获得栈中对象 | 无法注入 |
| HttpServletRequest类 | ActionContext. get( StrutsStatics. HTTP_REQUEST) | 一次Http请求 | 无方便的方法 | 实现ServletRequestAware接口 |
| request的Map | ActionContext. get("request") | 一次Http请求 | 使用“#request”再加上key,如“#request.name”或者“#request['name']” | 实现RequestAware接口 |
| parameters的Map | ActionContext. get( "parameters") | 一次Http请求 | 使用“# parameters”再加上key,如“#parameters .name”或者“#parameters ['name']” | 实现ParameterAware接口 |
| HttpServletSession类 | 无(需通过HttpServletRequest来获得) | 一次Http Session会话 | 无方便的方法 | 无法注入 |
| session的Map | ActionContext. get("session") | 每次请求创建,但在一次Http Session会话中数据都是一样的 | 使用“#session”再加上key,如“# session.name”或者“#session ['name']” | 实现SessionAware接口 |
| ServletContext类 | ActionContext. get( StrutsStatics. SERVLET_CONTEXT) | 网站项目启动后一直存在且唯一 | 无方便的方法 | 使用ServletContextAware接口 |
| application的Map | ActionContext.get( "application") | 每次请求时创建,但其中的数据是网站项目启动后一直存在且共享 | 使用“# application”再加上key,如“#application .name”或者“#application ['name']” | 使用ApplicationAware接口 |
五、ActionContext中到底有哪些数据
| key | key的声明处 | value的类型 | value.toString() |
|
com. opensymphony. xwork2. dispatcher. HttpServletRequest |
StrutsStatics. HTTP_REQUEST | org. apache. struts2. dispatcher. StrutsRequestWrapper | org. apache. struts2. dispatcher. StrutsRequestWrapper @10984e0 |
| application | 无 | org. apache. struts2. dispatcher. ApplicationMap | 略 |
| com. opensymphony. xwork2. ActionContext. locale | ActionContext. LOCALE | java. util. Locale | zh_CN |
| com. opensymphony. xwork2. dispatcher. HttpServletResponse | StrutsStatics. HTTP_RESPONSE | org. apache. catalina. connector. ResponseFacade | org. apache. catalina. connector. ResponseFacade @14ecfe8 |
|
xwork. NullHandler. createNullObjects |
Boolean | false | |
| com. opensymphony. xwork2. ActionContext. name | ActionContext. ACTION_NAME | String | index |
|
com.opensymphony. xwork2.ActionContext. conversionErrors |
ActionContext. CONVERSION_ERRORS |
java. util. HashMap | {} |
| com. opensymphony. xwork2. ActionContext. application | ActionContext. APPLICATION | org. apache. struts2. dispatcher. ApplicationMap | 略 |
| attr | 无 | org. apache. struts2. util. AttributeMap | org. apache. struts2. util. AttributeMap @133a2a8 |
| com. opensymphony. xwork2. ActionContext. container | ActionContext. CONTAINER | com. opensymphony. xwork2. inject. ContainerImpl | com. opensymphony. xwork2. inject. ContainerImpl @fc02c8 |
| com. opensymphony. xwork2. dispatcher. ServletContext | StrutsStatics. SERVLET_CONTEXT | org. apache. catalina. core. ApplicationContextFacade | org. apache. catalina. core. ApplicationContextFacade @11ad78c |
| com. opensymphony. xwork2. ActionContext. session | ActionContext. SESSION | org.apache.struts2. dispatcher.SessionMap | {} |
|
com.opensymphony. xwork2.ActionContext. actionInvocation |
ActionContext. ACTION_INVOCATION | com. opensymphony. xwork2. DefaultActionInvocation | com. opensymphony. xwork2. DefaultActionInvocation @13d4497 |
| xwork. MethodAccessor. denyMethodExecution | 笔者很懒,没有找 | Boolean | false |
| report. conversion. errors | 笔者很懒,没有找 | Boolean | false |
| session | 无 | org. apache. struts2. dispatcher. SessionMap | {} |
| com. opensymphony. xwork2. util. ValueStack. ValueStack | ValueStack.VALUE_STACK | com. opensymphony. xwork2. ognl. OgnlValueStack | com. opensymphony. xwork2. ognl. OgnlValueStack @16237fd |
| request | 无 | org. apache. struts2. dispatcher. RequestMap | 略 |
| action | 笔者很懒,没有找 | com. example. MyAction | 略 |
| struts. actionMapping | 笔者很懒,没有找 | org. apache. struts2. dispatcher. mapper. ActionMapping | org. apache. struts2. dispatcher. mapper. ActionMapping @892cc5 |
| parameters | 无 | java. util. HashMap | {} |
| com. opensymphony. xwork2. ActionContext. parameters | ActionContext.PARAMETERS | java. util. TreeMap | {} |
其实看上面的内容可能还是对值栈不是太了解,还是糊涂,不过没关系,http://www.cnblogs.com/whgk/p/6600393.html这篇博客对ValueStack和ActionContext的关系讲的还挺清楚的,下一篇博客把OGNL学习一遍可能就好理解了。
Struts2之ValueStack、ActionContext的更多相关文章
- struts2重点——ValueStack和OGNL
一.值栈(ValueStack) 1.实现类:OGNLValueStack 2.对象栈:CompoundRoot(针对的是类级别的) (1)继承自 ArrayList —— 先进后出 (2)提供了栈的 ...
- Struts2:ValueStack
一.ValueStack 1 .ValueStack是一个接口,在struts2中使用OGNL(Object-Graph Navigation Language)表达式实际上是使用 ...
- 浅析=======Struts2之==========valueStack
今天刚学习了struts2的valueStack,在这里把自己学到的做个分享,说道valueStack就不得不提OGNL表达式=== struts2工作流程 1.OGNL(Object Graph N ...
- struts2 OGNL ValueStack概念理解 # % $ 的区别
http://blog.csdn.net/tjujacob/article/details/8117659 —————————————————————————————————————————————— ...
- Struts2中ValueStack结构和总结
[ValueStack和ActionContext的关系] 首先,从结构上来看ValueStack是ActionContext的一个组成部分,是对ActionContext功能的扩展.ActionCo ...
- 十八、ValueStack&ActionContext(非常重点:值栈)
ValueStack&ActionContext(非常重点:值栈) 1.针对用户的每次动作访问,都会创建属于自己的ValueStack对象 2.ValueStack中的的常用方法:功能一定要知 ...
- struts2中valueStack,stackContext以及actionContext的关系
一,首先给出三者的定义 1.valueStack: 里面存放的是Action类中通过set方法设置的属性值(表单传过来的值等),由OGNL框架实现; 2.stackContext: 也是用来存值的,s ...
- Struts2中 ValueStack、ActionContext、ServletContext、request、session等 表格解析
变量 从ActionContext中获得 生命周期 用Ongl来读取值 使用ServletConfigInterceptor来注入 ActionContext类 静态方法ActionContext. ...
- struts2学习笔记--ActionContext对象
什么是ActionContext? ActionContext是Map结构的容器,ActionContext是Action的上下文,类比ServletContext,存放着Action执行过程中的数据 ...
随机推荐
- 【转】机器学习在B2B的应用
原文地址:http://www.mbtmag.com/blog/2017/04/artificial-intelligence-making-it-work-industrial-companies? ...
- Chapter3_操作符_关系操作符
java中的关系操作符有等于“=”,不等于“!=”,大于“>”,小于“<”,大于等于“≥”,小于等于“≤”等.这些都不再赘述了,有一个有意思的点是关于等价性的讨论. 在java中测试两个对 ...
- 【ZooKeeper】ZooKeeper安装及简单操作
ZooKeeper介绍 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一 ...
- centos7 安装maven
进入指定目录 cd /usr/local/src/ 下载maven 包 wget http://mirrors.hust.edu.cn/apache/maven/maven-3/3.1.1/bin ...
- C语言基础课第五次作业
PTA第五次作业 7-2 统计一行文本中的单词个数 一.程序代码 #include<stdio.h> int main(void) { ]; ,word=; char c; gets(st ...
- 利用python监测linux上的服务(简单实现服务宕掉自动发送邮件)
python 这里用到了四个python 模块 : import time (时间模块) import re (正则模块) import socket (监测端口模块)import yagmail ( ...
- Android-broadcast静态动态广播
广播的静态和动态类型 静态广播: 1.继承之broadcastreceiver public class MyStaticBroadcastReceiver extends BroadcastRece ...
- utf-8转gb2312
近日在对一个json串进行转码时,显示中文乱码,原因是json串编码方式为utf-8,而我程序在windows上采用的是多字节编码方式,即采用gb2312编码.这里就存在一个utf-8到gb2312的 ...
- 在Azure DevOps Server(TFS系统)中部署回退/回滚方案(Rollback)
概述 Azure DevOps Server(之前名TFS)是微软公司实现软件研发.测试和部署一体化的全流程解决方案.在近几年的研发过程中,Azure DevOps Server 大幅增强了软件部署过 ...
- MyBatis 源码分析 - SQL 的执行过程
* 本文速览 本篇文章较为详细的介绍了 MyBatis 执行 SQL 的过程.该过程本身比较复杂,牵涉到的技术点比较多.包括但不限于 Mapper 接口代理类的生成.接口方法的解析.SQL 语句的解析 ...