Java中的值栈
OGNL表示式使用 和 值栈
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
* xwork 提供 OGNL表达式
* ognl-3.0.5.jar
OGNL 是一种比EL 强大很多倍的语言
OGNL 提供五大类功能
1、支持对象方法调用,如xxx.doSomeSpecial();
2、支持类静态的方法调用和值访问
3、访问OGNL上下文(OGNL context)和ActionContext; (重点 操作ValueStack值栈 )
4、支持赋值操作和表达式串联
5、操作集合对象。
1、 使用OGNL访问 对象方法 和 静态方法
* OGNL 在jsp 结合 struts2 标签库 使用 , <s:property value="ognl表达式" /> 执行 ognl表达式
调用 实例方法 : 对象.方法() ---- <s:property value="'hello,world'.length()"/>
调用 静态方法 : @[类全名(包括包路径)]@[方法名] --- <s:property value="@java.lang.String@format('您好,%s','小明')"/>
* 使用 静态方法调用 必须 设置 struts.ognl.allowStaticMethodAccess=true
2、 访问OGNL上下文(OGNL context)和ActionContext
OGNL上下文(OGNL context) 对象 ----- 值栈 ValueStack
什么是值栈 ValueStack ?
值栈:简单的说,就是存放action的堆栈,当我们提交一个请求到服务器端 action时,就有个堆栈,如果action在服务器端进行跳转,所有action共用一个堆栈,当需要保存在action中的数据时,首先从栈顶开始 搜索,若找到相同的属性名(与要获得的数据的属性名相同)时,即将值取出,但这种情况可能出现找到的值不是我们想要的值,那么解决此问题需要用TOP语法 和N语法来进行解决。
0
ValueStack 是 struts2 提供一个接口,实现类 OgnlValueStack ---- 值栈对象 (OGNL是从值栈中获取数据的 )
每个Action实例都有一个ValueStack对象 (一个请求 对应 一个ValueStack对象 )
在其中保存当前Action 对象和其他相关对象 (值栈中 是有Action 引用的 )
Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性中,request中 (值栈对象 是 request一个属性)
valueStack vs = request.getAttribute("struts.valueStack");
问题二 : 值栈的内部结构 ?
值栈由两部分组成
ObjectStack (root): Struts 把动作和相关对象压入 ObjectStack 中--List
ContextMap (context): Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中
Struts 会把下面这些映射压入 ContextMap 中
parameters: 该 Map 中包含当前请求的请求参数 ?name=xxx
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application 对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application
ValueStack中 存在root属性 (CompoundRoot) 、 context 属性 (OgnlContext )
* CompoundRoot 就是ArrayList
* OgnlContext 就是 Map
context 对应Map 引入 root对象
* context中还存在 request、 session、application、 attr、 parameters 对象引用
* OGNL表达式,访问root中数据时 不需要 #, 访问 request、 session、application、 attr、 parameters 对象数据 必须写 #
* 操作值栈 默认指 操作 root 元素
问题三 : 值栈对象的创建 ,ValueStack 和 ActionContext 是什么关系 ?
值栈对象 是请求时 创建的
doFilter中 prepare.createActionContext(request, response);
* 创建ActionContext 对象过程中,创建 值栈对象ValueStack
* ActionContext对象 对 ValueStack对象 有引用的 (在程序中 通过 ActionContext 获得 值栈对象 )
Dispatcher类 serviceAction 方法中 将值栈对象保存到 request范围
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
问题四 : 如何获得值栈对象
获得值栈对象 有两种方法
ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
ValueStack valueStack2 = ActionContext.getContext().getValueStack();
问题五: 向值栈保存数据 (主要针对 root)
两种方式
// 将数据保存root的索引0位置,放置到第一个元素 ArrayList add(0,element);
valueStack.push("itcast");
// 在值栈创建参数map, 将数据保存到map中
valueStack.set("company", "数据");
在jsp中 通过 <s:debug /> 查看值栈的内容
问题六: 在JSP中获取值栈的数据
访问root中数据 不需要#
访问 其它对象数据 加 #
通过下标获取root中对象
<s:property value="[0].top"/> //取值栈顶对象
直接在root中查找对象属性 (自上而下自动查找)
valueStack:<s:property value="username"/>
在OgnlContext中获取数据
request:<s:property value="#request.username"/>
session:<s:property value="#session.username"/>
application:<s:property value="#application.username"/>
attr:<s:property value="#attr.username"/>
parameters:<s:property value="#parameters.cid[0]"/>
valueStack对象 保存在request范围, 值栈生命周期 就是 request的生命周期 ,值栈的内部结构(root、ognlContext)
3、 值栈在开发中应用
主流应用 : 值栈 解决 Action 向 JSP 传递 数据问题
Action 向JSP 传递数据处理结果 ,结果数据有两种形式
1) 消息 String类型数据
this.addFieldError("msg", "字段错误信息");
this.addActionError("Action全局错误信息");
this.addActionMessage("Action的消息信息");
* fieldError 针对某一个字段错误信息 (常用于表单校验)、actionError (普通错误信息,不针对某一个字段 登陆失败)、 actionMessage 通用消息
在jsp中使用 struts2提供标签 显示消息信息
<s:fielderror fieldName="msg"/>
<s:actionerror/>
<s:actionmessage/>
2) 数据 (复杂类型数据)
使用值栈 valueStack.push(products);
哪些数据默认会放入到值栈 ???
1)每次请求,访问Action对象 会被压入值栈 ------- DefaultActionInvocation 的 init方法 stack.push(action);
* Action如果想传递数据给 JSP,只有将数据保存到成员变量,并且提供get方法就可以了
2)ModelDriven 接口 有一个单独拦截器
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
在拦截器中 ,将model对象 压入了 值栈 stack.push(model);
user.usernae ---------------?><input name="username"/>
* 如果Action 实现ModelDriven接口,值栈默认栈顶对象 就是model对象
4、 值栈的数据 通过EL访问
问题七:为什么 EL也能访问值栈中的数据
ActionContext.getContext().getSession().setAttribute("key","value");
${requestScope.username}----------->requst.getAttribute("username");------>重写getAttribute()方法,没有找到数据的情况下,继续找ValueStack
StrutsPreparedAndExecuteFilter的doFilter代码中 request = prepare.wrapRequest(request);
* 对Request对象进行了包装 ,StrutsRequestWrapper
* 重写request的 getAttribute
Object attribute = super.getAttribute(s);
if (attribute == null) {
attribute = stack.findValue(s);
}
访问request范围的数据时,如果数据找不到,去值栈中找
* request对象 具备访问值栈数据的能力 (查找root的数据)
5、 OGNL表达式 常见使用
#、 % 、$ 符号使用
1) # 的 使用
用法一 # 代表 ActionContext.getContext() 上下文
<s:property value="#request.name" /> ------> ActionContext().getContext().getRequest().getAttribute("name");
#request
#session
#application
#attr
#parameters
用法二 : 不写# 默认在 值栈中root中进行查找
<s:property value="name" /> 在root中查找name属性
* 查询元素时,从root的栈顶元素 开始查找, 如果访问指定栈中元素 <s:property value="[1].top.name" /> 访问栈中第二个元素name属性
* 访问第二个元素对象 <s:property value="[1].top" />
用法三 :进行投影映射 (结合复杂对象遍历 )
s:iterator标签在进行遍历时,会将var中保存的这个对象,在root中,和context中都放一份
所以在<s:property value=""/> value属性加不加#都可以访问
1)集合的投影(只输出部分属性
<h1>遍历集合只要name属性</h1>
<s:iterator value="products.{name}" var="pname">
<s:property value="#pname"/>
</s:iterator>
2)遍历时,对数据设置条件
<h1>遍历集合只要price大于1500商品</h1>
<s:iterator value="products.{?#this.price>1500}" var="product">
<s:property value="#product.name"/> --- <s:property value="#product.price"/>
</s:iterator>
3)综合
<h1>只显示价格大于1500 商品名称</h1>
<s:iterator value="products.{?#this.price>1500}.{name}" var="pname">
<s:property value="#pname"/>
</s:iterator>
用法四: 使用#构造map集合
经常结合 struts2 标签用来生成 select、checkbox、radio
<h1>使用#构造map集合 遍历</h1>
#{key:value,kye1:value1}
<s:iterator value="#{'name':'aaa','age':'20', 'hobby':'sport' }" var="entry">
key : <s:property value="#entry.key"/> , value: <s:property value="#entry.value"/> <br/>
</s:iterator>
2) %的使用
用法一: 结合struts2 表单标签使用, 通过%通知struts, %{}中内容是一个OGNL表达式,进行解析
<s:textfield name="username" value="%{#request.username}"/>
<s:textfield name="username" value="<s:property value='#request.username'/>" />是错误的
用法二: 设置ognl表达式不解析 %{'ognl表达式'}
<s:property value="%{'#request.username'}"/>
3)$的使用
用法一 :用于在国际化资源文件中,引用OGNL表达式
在properties文件 msg=欢迎您, ${#request.username}
在页面
<s:i18n name="messages">
<s:text name="msg"></s:text>
</s:i18n>
* 自动将值栈的username 结合国际化配置信息显示
用法二 :在Struts 2配置文件中,引用OGNL表达式
<!-- 在Action 提供 getContentType方法 -->
<param name="contentType">${contentType}</param>
* ${contentType} 读取值栈中contentType数据,在Action提供 getContentType 因为Action对象会被压入值栈,
contentType是Action属性,从值栈获得
结论: #用于写ognl表达式获取数据,% 控制ognl表达式是否解析 ,$ 用于配置文件获取值栈的数据
五、 struts2 标签库
tag-reference.html 就是 struts2 标签规范
1、 通用标签库 的学习
<s:property> 解析ognl表达式,设置默认值,设置内容是否HTML转义
<s:set> 对比c:set向四个数据范围保存数据
<s:iterator> 遍历值栈中数据 <c:forEach />
<s:if> <s:elseif> <s:else> 进行条件判断 -------- elseif 可以有多个
<s:url> 进行URL重写(追踪Session ) ,结合s:param 进行参数编码
* <s:url action="download" namespace="/" var="myurl">
<s:param name="filename" value="%{'MIME协议简介.txt'}"></s:param>
</s:url>
<s:property value="#myurl"/>
<s:a> 对一个链接 进行参数编码
* <s:a action="download" namespace="/" >下载MIME协议简介.txt
<s:param name="filename" value="%{'MIME协议简介.txt'}"></s:param>
</s:a>
2、 UI标签库的学习 (Form标签)
使用struts2 form标签 好处 : 支持数据回显 , 布局排版(基于Freemarker 模板定义 )
struts2 表单标签 value属性。 必须写 %{} 进行设值
使用struts2表单标签前, 必须配置 StrutsPrepareAndExecuteFilter
<s:form> 表单标签
<s:form action="regist" namespace="/" method="post" theme="xhtml"> --- theme="xhtml" 默认布局样式
<s:textfield> 生成 <input type="text" >
<s:password > 生成 <input type="password" >
<s:submit type="submit" value="注册"/> 生成 <input type="submit" >
<s:reset type="reset" value="重置" /> 生成 <input type="reset" >
* struts2 除了支持JSP之外,支持两种模板技术 Velocity (扩展名 .vm ) 、 Freemarker (扩展名 .ftl)
<s:textarea> 生成 <textarea> 多行文本框
<s:checkboxlist> 生成一组checkbox
* 使用ognl构造 Map (看到值和提交值 不同时)
* <s:checkboxlist list="#{'sport':'体育','read':'读书','music':'音乐' }" name="hobby"></s:checkboxlist>
<s:radio> 生成一组radio
* 使用 ognl构造 List (看到内容和提交值 相同时)
* <s:radio list="{'男','女'}" name="gender"></s:radio>
<s:select> 生成一个<select>
* <s:select list="{'北京','上海','南京','广州'}" name="city"></s:select>
struts2 开发 密码框 默认不回显
<s:password name="password" id="password" showPassword="true"/>
3、 页面元素主题设置
default.properties ---- struts.ui.theme=xhtml 设置struts2 页面元素使用默认主题
struts.ui.templateSuffix=ftl 默认模板引擎 Freemarker
修改主题
方式一 :<s:textfield name="username" label="用户名“ theme="simple"></s:textfield> 只对当前元素有效
方式二 :<s:form action="" method="post" namespace="/ui“ theme="simple"> 对form中所有元素有效
方式三 : struts.xml
<constant name="struts.ui.theme" value="simple"></constant> 修改默认主题样式,页面所有元素都有效
优先级 : 方式一 > 方式二 > 方式三
Java中的值栈的更多相关文章
- Java中堆和栈的区别(转)
栈与堆都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new. ...
- 关于Struts2中的值栈与OGNL表达式
1.1.1 OGNL概述: Object Graphic Navigation Language(对象图导航语言)的缩写 * EL :OGNL比EL功能强大很多倍. 它是一个开源项目. ...
- Struts2中的值栈
一 什么是值栈 值栈: struts2中提供的一种类似于域对象的工具, 用于struts2中的存值和取值. 每次访问Action的时候, 都会创建一个action对象, 而每个action对象中都存在 ...
- 为什么说Java中只有值传递
本文转载自公众号 Hollis 对于初学者来说,要想把这个问题回答正确,是比较难的.在第二天整理答案的时候,我发现我竟然无法通过简单的语言把这个事情描述的很容易理解,遗憾的是,我也没有在网上找到哪篇文 ...
- 为什么说Java中只有值传递(转载)
出处:https://www.hollischuang.com/archives/2275 关于这个问题,在StackOverflow上也引发过广泛的讨论,看来很多程序员对于这个问题的理解都不尽相同, ...
- 为什么说Java中只有值传递----说服自己
在开始深入讲解之前,有必要纠正一下大家以前的那些错误看法了.如果你有以下想法,那么你有必要好好阅读本文. 错误理解一:值传递和引用传递,区分的条件是传递的内容,如果是个值,就是值传递.如果是个引用,就 ...
- Java中返回值定义为int类型的 方法return 1返回的是int还是Integer&&finally中return问题
在Java中返回值定义为int类型的 方法return 1:中返回的是Integer值,在返回的时候基本类型值1被封装为Integer类型. 定义一个Test类,在异常处理try中和finally中分 ...
- Java中只有值传递,(及值传递与引用传递详解)
首先呢,我们来说一下值传递与引用传递的区别(这两个玩意儿实在调用函数的时候提到的) 比如说 code( a) code( int a ) code(a)是调用函数,a是我们原本函数的一个值类型,然后使 ...
- 为什么说 Java 中只有值传递?
对于初学者来说,要想把这个问题回答正确,是比较难的.在第二天整理答案的时候,我发现我竟然无法通过简单的语言把这个事情描述的很容易理解,遗憾的是,我也没有在网上找到哪篇文章可以把这个事情讲解的通俗易懂. ...
随机推荐
- debian服务器上不了网,缺少默认网关
debian服务器上不了网,缺少默认网关 root@hbg:/# route -nKernel IP routing tableDestination Gateway Genm ...
- 关于string的对象引用
什么都不说了, 一切都在代码里: Console.WriteLine(object.ReferenceEquals(c5, c4)); //False ...
- POJ 2083 Fractal 分形
去年校赛团队赛就有一道分形让所有大一新生欲生欲死…… 当时就想学了 结果一直拖到…… 今天上午…… 马上要省选了 才会一点基础分形…… 还是自己不够努力啊…… 分形主要是要找到递归点…… 还有深度…… ...
- Gentoo本地化设置--时区、时钟、字体、中文环境
时区 你需要选择时区让系统知道你的地理位置,以保持正确的时间.在/usr/share/zoneinfo中查找你的时区.然后在/etc/conf.d/clock中设置时区.请忽略/usr/share/z ...
- ios 将图片变成圆形
#pragma mark - 将图片转换成圆形 -(UIImage*) circleImage:(UIImage*) image withParam:(CGFloat) inset { UIGraph ...
- ubuntu下安装UltraEdit
在windows下常年使用UltraEdit来查看log,现在突然切换到ubuntu下,系统自带的Text Editor相当不适应:只有自己安装了. 首先,需要下载安装包,可以去:http://www ...
- c题 Registration system
Description A new e-mail service "Berlandesk" is going to be opened in Berland in the near ...
- 转 shell awk 使用详解
awk简介 awk: 中文意思是报告生成器 能够根据我们输入的信息,将信息格式化以后显示,将定义好的信息以比较美观(直观)的方式显示出来出现比较早,继而出现了new awk(nawk)在windows ...
- HDU2544-最短路(最短路模版题目)
Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要 ...
- 转:JMeter基础--逻辑控制器Logic Controller
1.ForEach控制器 ForEach控制器在用户自定义变量中读取一系列相关的变量.该控制器下的采样器或控制器都会被执行一次或多次,每次读取不同的变量值.所以ForEach总是和User Defin ...