【Struts2】Ognl与ValueStack
一、OGNL
1.1 概述
OGNL
是Object-Graph Navigation Language
的缩写,它是一种功能强大的表达式语言.比el表达式功能强大。Struts2
将ognl
表达式语言,集成当sturts2
框架中,做为它的默认表达式语言。OGNL
中有一个OgnlContext
,它可以设置root与非root .root中数据获取时,不需要加#,而非root中数据在获取时,需要加上#
1.2 OGNL 五大类功能
- 1、支持对象方法调用,如
xxx.doSomeSpecial();
- 2、支持类静态的方法调用和值访问
- 3、访问OGNL上下文(OGNL context)和
ActionContext
; (重点 操作ValueStack值栈 ) - 4、支持赋值操作和表达式串联
- 5、操作集合对象。
1.3 演示
- 在struts2中使用ognl表达式
需要结合struts2的标签使用`
<s:property value="'abc'.length()"/> 演示对象调用方法
<s:property value="@java.lang.Math@max(10,20)"/> 演示静态成员访问.
注意:在struts2中使用静态成员访问,必须设置一个常量:
struts.ognl.allowStaticMethodAccess=false
二、ValueStack
2.1 概述
- ValueStack,它是一个接口
com.opensymphony.xwork2.util.ValueStack
。我们使用它是将其做为一个容器,用于携带action数据到页面.在页面上通过ognl表达式获取数据 - ValueStack主要是将action数据携带到页面上,通过ognl获取数据
- 1.ValueStack有一个实现类叫OgnlValueStack.
- 2.每一个action都有一个ValueStack.(一个请求,一个request,一个action,一个valueStack) ValueStack生命周期就是request生命周期。
- 3.ValueStack中存储了当前action对象以及其它常用web对象(
request,session,application.parameters
) - 4.struts2框架将valueStack以“
struts.valueStack
”为名存储到request域中。
- 1.ValueStack有一个实现类叫OgnlValueStack.
2.2 ValueStack结构
ValueStack
中 存在root
属性 (CompoundRoot
) 、context
属性 (OgnlContext
)CompoundRoot
就是ArrayList
,list
集合中存储的是action
相关信息,OgnlContext
就是Map
,map
集合中存储的是相关映射信息,包含paramters,request,session,application attr
等。- 我们想要从list中获取数据,可以不使用#号.(它就是ognl的root)
- 如果从map中获取数据,需要使用#. (其实在struts2中的map--context其实就是ognlContext)
2.3 结论
- ValueStack它有两部分 List Map
- 在struts2中List就是root Map就是ognlContext.
默认情况下,在struts2中从valueStack获取数据从root中获取。
值栈对象的创建 ,ValueStack 和 ActionContext 是什么关系 ?
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
stack = ctx.getValueStack();
}
ValueStack是每一次请求时,都会创建.
在ActionContext中持有了valueStack的引用。
2.3 一些问题
- 获得值栈对象
对于ValueStack获取有两种方式:
- 1.通过 request获取
ValueStack vs=(ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
- 2.通过ActionContext获取.
ValueStack vs=ActionContext.getContext().getValueStack();
向值栈保存数据 (主要针对 root),主要有两个方法
- push(Object obj)------->底层就是 root.add(0,obj) 将数据存储到栈顶。
- set(String name,Object obj);----->底层是将数据封装到HashMap中,在将这个HashMap通过push存储。
- 在jsp中 通过 查看值栈的内容
在JSP中获取值栈的数据
- root中数据不需要#,而context中数据需要#
1.如果栈顶是一个Map集合,获取时,可以直接通过Map集合的key来获取value.
<s:property value="username"/>
2.如果栈顶数据不是一个Map,没有key值,可以使用序号来获取。
<s:property value="[0]"> 从0的位置向下查找所有。
<s:property value="[0].top"> 只查找0位置上数据。
如何获取OgnlContext中数据:
1.request数据 request.setAttribute()
2.session数据 session.setAttribute()
3.application数据 application.setAttribute()
4.attr 依次从request,session.application中查找
5.parameters 获取请求参数
ValueStack主流应用:就是解决将action数据携带到jsp页面。
1.文本(字符串)
1.fieldError 校验数据错误信息提示
2.actionError 关于逻辑操作时错误信息(例如登录失败)
3.message 就是一个信息.
this.addFieldError("msg", "字段错误信息");
this.addActionError("Action全局错误信息");
this.addActionMessage("Action的消息信息");
* fieldError 针对某一个字段错误信息 (常用于表单校验)、actionError (普通错误信息,不针对某一个字段 登陆失败)、 actionMessage 通用消息
在jsp中使用 struts2提供标签 显示消息信息
<s:fielderror fieldName="msg"/>
<s:actionerror/>
<s:actionmessage/>
- 2.复杂数据
可以使用valueStack存储.
在action中存储数据:
List<User> users = new ArrayList<User>();
users.add(new User("tom", "123", 20, "男"));
users.add(new User("james", "456", 21, "男"));
users.add(new User("fox", "789", 26, "男"));
vs.push(users);
在页面上获取数据:
使用了<s:iterator>标签来迭代集合。
<s:iterator value="[0].top" var="user"> 这是将集合中迭代出来每一个元素起个名称叫user,而user是存储在context中,不在root中.l
<s:iterator value="[0].top" var="user">
username:<s:property value="#user.username"/><br>
password:<s:property value="#user.password"/>
<hr>
</s:iterator>
注意:如果我们在使用<s:iterator>进行迭代时,没有给迭代出的元素起名.
<s:iterator value="[0].top">
username:<s:property value="username"/><br>
password:<s:property value="password"/>
<hr>
</s:iterator>
关于默认压入到valueStack中的数据.
- 1.访问的action对象会被压入到valueStack中.
- DefaultActionInvocation 的 init方法 stack.push(action);
- Action如果想传递数据给 JSP,只有将数据保存到成员变量,并且提供get方法就可以了
2.ModelDriveInterceptor会执行下面操作
ModelDriven modelDriven = (ModelDriven) action;
ValueStack stack = invocation.getStack();
Object model = modelDriven.getModel();
if (model != null) {
stack.push(model);
}
- 将实现了ModelDrive接口的action中getModel方法的返回值,也就是我们所说的model对象压入到了valueStack.
- 1.访问的action对象会被压入到valueStack中.
为什么el表达式可以访问valueStack中数据?
- struts2框架中所使用的request对象,是增强后的request对象。
${username}---->request.getAttribute("username");
- 增强后的request,会首先在request域范围查找,如果查找不到,会在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的数据)
三、OGNL表达式常见使用符号
3.1 #号
用法一,
#
代表 ActionContext.getContext() 上下文
<s:property value="#request.name" /> ActionContext().getContext().getRequest().get("name");
#request
#session
#application
#attr
#parameters
用法二,不写# 默认在 值栈中root中进行查找
<s:property value="name" /> 在root中查找name属性
* 查询元素时,从root的栈顶元素 开始查找, 如果访问指定栈中元素
<s:property value="[1].name" /> 访问栈中第二个元素name属性
* 访问第二个元素对象 <s:property value="[1].top" />
用法三,进行投影映射 (结合复杂对象遍历 )
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>
<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>
3.2 %号
- 有些标签的value属性自动解析ognl表达式,
- 比如
<s:property value="表达式" />
- 但是有些标签是不自动解析的
- 比如:
<s:textfild value="表达式"/>
%作用:就是用于设定当前是否要解析其为 ognl表达式.
%{表达式}
当前表达式会被做为ognl解析.%{'表达式'}
当前表达式不会被做为ognl解析。
3.3 $号
- $作用:就是在配置文件中使用ognl表达式来获取valueStack中数据.
1.struts.xml
<result type="stream">
<param name="contentType">${contentType}</param>
</result>
(在Action中有一个getContentType() 方法)此处在上传文件的地方有讲解
2.在校验文件中使用
${min} ${max}
${minLength} ${maxLength}
3.在国际化文件中使用
在properties文件中
username=${#request.username}
在jsp页面
<s:text name="username">
总结: #就是用于获取数据 %就是用于设置是否是ognl表达式 $就是在配置文件中使用ognl.
【Struts2】Ognl与ValueStack的更多相关文章
- Struts2第九篇【OGNL、valueStack详解】
什么是OGNL表达式? OGNL是Object Graphic Navigation Language 是操作对象属性的开源表达式. Struts2框架使用OGNL作为默认的表达式语言. 为什么我们学 ...
- Struts2【OGNL、valueStack】就是这么简单
什么是OGNL表达式? OGNL是Object Graphic Navigation Language 是操作对象属性的开源表达式. Struts2框架使用OGNL作为默认的表达式语言. 为什么我们学 ...
- [ SSH框架 ] Struts2框架学习之三(OGNl和ValueStack值栈学习)
一.OGNL概述 1.1 什么是OGNL OGNL的全称是对象图导航语言( object-graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可 ...
- struts2 OGNL ValueStack概念理解 # % $ 的区别
http://blog.csdn.net/tjujacob/article/details/8117659 —————————————————————————————————————————————— ...
- Struts2之OGNL与ValueStack
时间:2017-1-12 12:02 --OGNL1.OGNL表达式是什么 OGNL的全称是Object-Graph Navigation Language的缩写,中文名是对象图导航语言,它是一 ...
- Struts2(Ognl)
OGNL(Object-Graph Navigation Language)全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者调用对象的方法,能够遍历整 ...
- 【Java EE 学习 36】【struts2】【struts2系统验证】【struts2 ognl值栈】【struts2 ongl标签】【struts2 UI标签】【struts2模型驱动和令牌机制】
一.struts2系统验证 1.基于struts2系统验证的方式实际上就是通过配置xml文件的方式达到验证的目的. 2.实际上系统校验的方法和手工校验的方法在底层的基本实现是相同的.但是使用系统校验的 ...
- 十九、利用OGNL获取ValueStack中:根栈和contextMap中的数据
利用OGNL获取ValueStack中:根栈和contextMap中的数据 原则:OGNL表达式如果以#开头,访问的contextMap中的数据 如果不以#开头,是访问的根栈中的对象的属性(List集 ...
- struts2 与 OGNL 表达式,jsp中 利用ognl 在valuestack中取值
在Struts2中,一个请求在终于到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是 ...
随机推荐
- 免费申请https
https://blog.csdn.net/MariaOzawa/article/details/81877756 实测有效
- layer弹框层学习笔记
这里对layer的笔记只是大概记录一下其使用过程,以便后续使用时快速回顾,更详细使用及介绍参考官网实例.链接在本文末 一 .初步了解layer-弹层之美 layer是一款近年来备受青睐的web弹层组件 ...
- spring注入注解
常见注解有Autowired.Resource.Qualifier.Service.Controller.Repository.Component. @Resource装配顺序 1. 如果同时指定了n ...
- golang web框架设计2:自定义路由
继续学习谢大的Go web框架设计 HTTP路由 http路由负责将一个http的请求交到对应的函数处理(或者一个struct的方法),路由在框架中相当于一个事件处理器,而这个时间包括 用户请求的路径 ...
- Flutter 的一些小技巧
1. 获取状态栏高度 import 'dart:ui'; MediaQueryData.fromWindow(window).padding.top 2. 设置AppBar的高度 Scaffold( ...
- Jmeter 逻辑控制器 之 ForEach 控制器
一.认识 ForEach 控制器 如下,创建一个 ForEach 控制器 设置界面如下: 输入变量前缀:要进行循环读取的变量前缀 Start index for loop (exclusive):循环 ...
- shell脚本执行出现“期待整数表达式”
在执行shell时一直出现“integer expression expected”,找了很久也没发现那个地方出错.翻了笔记发现-le并不错啊,甚至还怀疑零是不是整数还特意上网搜了下 -_- . 最后 ...
- 最新 汇量科技java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿. 汇量科技等10家互联网公司的校招Offer,因为某些自身原因最终选择了 汇量科技.6.7月主要是做系统复习.项目复盘.Le ...
- golang的定时器NewTimer、NewTicker使用
package main import ( "fmt" "sync" "time" ) /** *ticker只要定义完成,从此刻开始计时, ...
- Fourier serie
你眼中看似落叶纷飞变化无常的世界,实际只是躺在上帝怀中一份早已谱好的乐章. 时域和频域就像观察一个物体一样,一个是主视图的,一个是侧视图. 1.在有限区间上由任意图形定义的任意函数都可以表示为单纯的正 ...