OGNL是Object Graph Navigation Language的简称,详细相关的信息可以参考:http://www.ognl.org。这里我们只涉及Struts2框架中对OGNL的基本支持。
Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:
1. 支持对象方法调用,如xxx.doSomeSpecial();
2. 支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;
3. 支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(),这个表达式会返回80;
4. 访问OGNL上下文(OGNL context)和ActionContext;
5. 操作集合对象。
#、%和$这三个符号的使用:
“#”主要有三种用途:
1. 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:
名称
作用
例子
parameters
包含当前HTTP请求参数的Map
#parameters.id[0]作用相当于request.getParameter("id")
request
包含当前HttpServletRequest的属性(attribute)的Map
#request.userName相当于request.getAttribute("userName")
session
包含当前HttpSession的属性(attribute)的Map
#session.userName相当于session.getAttribute("userName")
application
包含当前应用的ServletContext的属性(attribute)的Map
#application.userName相当于application.getAttribute("userName")
attr
用于按request > session > application顺序访问其属性(attribute)
#attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止
2. 用于过滤和投影(projecting)集合,如books.{?#this.price<100};
3. 构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:
<hr />
<h3>%的用途</h3>
<p><s:url value="#foobar['foo1']" /></p>
<p><s:url value="%{#foobar['foo1']}" /></p>
OGNL是一个对象,属性的查询语言。在OGNL中有一个类型为Map的Context(称为上下文),在这个上下文中有一个根元素(root),对根元素的属性的访问可以直接使用属性名字,但是对于其他非根元素属性的访问必须加上特殊符号#。
在Struts2中上下文为ActionContext,根元素位Value Stack(值堆栈,值堆栈代表了一族对象而不是一个对象,其中Action类的实例也属于值堆栈的一个)。ActionContext中的内容如下图:
|--application
|
|--session
context map---|
|--value stack(root)
|
|--request
|
|--parameters
|
|--attr (searches page, request, session, then application scopes)
|–request
|
|–application
|
context map—|–OgnlValueStack(root) [ user, action, OgnlUtil, ... ]
|
|–session
|
|–attr
|
|–parameters
因为Action实例被放在Value Stack中,而Value Stack又是根元素(root)中的一个,所以对Action中的属性的访问可以不使用标记#,而对其他的访问都必须使用#标记。
我们可以使用”#requet”访问HttpServletRequest对象, “#session”访问HttpSession对象,但请注意”根对象”是什么?是ValueStack!
那么ValueStack是什么?值栈。也就是一组对象的堆栈。也就是说,在struts2中,根对象不是我们通常的一个对象,而是一组对象。我们可以push新的对象到值栈中,也可以弹出值栈的栈顶对象。如上图所示,假设我们将user对象push到值栈中,那么如下的表达式将与之前我们见过的表达式一样,具有相同的结果:
Java代码
name // 取用户的姓名
age // 取用户年龄
birthday // 取用户生日
customer.name // 取用户所属客户的名称
#request.parameters // 取请求参数
也就是说,我们使用name这个表达式的时候,ONGL会取”根对象”的name属性,但现在根对象是ValueStack!那么访问 ValueStack的name属性意味着什么呢?这意味着: ValueStack会先查看栈顶元素是否有name属性,如果有就返回该属性值,否则取出栈顶下的元素,继续查看,直到栈底为止。
以上就是OGNL表达式的核心概念,你理解了吗?下一步,你需要了进一步了解OGNL的语法,以发掘其更强大的功能
引用Action的属性
<s:property value="postalCode"/>
ActionContext中的其他非根(root)元素的属性可以按照如下的方式访问:
<s:property value="#session.mySessionPropKey"/> or
<s:property value="#session["mySessionPropKey"]"/> or
<s:property value="#request["mySessionPropKey"]/>
Action类可以使用ActionContext中的静态方法来访问ActionContext。
ActionContext.getContext().getSession().put("mySessionPropKey", mySessionObject);
OGNL与Collection(Lists,Maps,Sets)
生成List的语法为: {e1,e2,e3}.
<s:select label="label" name="name"
list="{'name1','name2','name3'}" value="%{'name2'}" />
上面的代码生成了一个HTML Select对象,可选的内容为: name1,name2,name3,默认值为:name2。
生成Map的语法为:#{key1:value1,key2:value2}.
<s:select label="label" name="name"
list="#{'foo':'foovalue', 'bar':'barvalue'}" />
上面的代码生成了一个HTML Select对象,foo名字表示的内容为:foovalue,bar名字表示的内容为:barvalue。
对于集合,OGNL提供了两个元素符:in和not in,其中in判断某个元素是否在指定集合中;not in则用于判断某个元素是否不在指定集合中。
判断一个对象是否在List内存在:
<s:if test="'foo' in {'foo','bar'}">
muhahaha
</s:if>
<s:else>
boo
</s:else>
<s:if test="'foo' not in {'foo','bar'}">
muhahaha
</s:if>
<s:else>
boo
</s:else>
取得一个List的一部分:
? – 所有满足选择逻辑的对象
^ - 第一个满足选择逻辑的对象
$ - 最后一个满足选择逻辑的对象
例如:
person.relatives.{? #this.gender == 'male'}
上述代码取得这个人(person)所有的男性(this.gender==male)的亲戚(relatives)
Lambda 表达式
OGNL支持简单的Lambda表达式语法,使用这些语法可以建立简单的lambda函数。
例如:
Fibonacci:
if n==0 return 0;
elseif n==1 return 1;
else return fib(n-2)+fib(n-1);
fib(0) = 0
fib(1) = 1
fib(11) = 89
OGNL的Lambda表达式如何工作呢?
Lambda表达式必须放在方括号内部,#this表示表达式的参数。例如:
<s:property value="#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" />
#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)]定义了一个Lambda表达式,
#fib(11) 调用了这个表达式。
所以上述代码的输出为:89
在JSP2.1中#被用作了JSP EL(表达式语言)的特殊记好,所以对OGNL的使用可能导致问题,
一个简单的方法是禁用JSP2.1的EL特性,这需要修改web.xml文件:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>true</el-ignored>
</jsp-property-group>
</jsp-config>
4.6节 Tag 语法
代码示例:
表达式
含义
<p>Username: ${user.username}</p>
一个在标准上下文中的JavaBean对象,可以适用Freemarker,Velocity,JSTL EL等(不是OGNL)。
<s:textfield name="username"/>
在Value Stack中的一个username属性。
<s:url id="es" action="Hello">
<s:param name="request_locale">
es
</s:param>
</s:url>
<s:a href="%{es}">Espanol</s:a>
引用Value Stack中属性的另外一种方法。
<s:property
name="#session.user.username" />
Session中的user对象的username属性。
<s:select
label="FooBar" name="foo"
list="#{'username':'trillian',
'username':'zaphod'}" />
一个简单的静态Map,和put("username","trillian")一样
Struts2在OGNL基础上的增强
1、值栈(ValueStack)
Struts2将OGNL上下文设置为Struts2中的ActionContext(内部使用的仍然是OgnlContext),并将值栈设为OGNL的根对象。
我们知道,OGNL上下文中的根对象可以直接访问,不需要使用任何特殊的“标记”,而引用上下文中的其他对象则需要使用“#”来标记。由于值栈是上下文中的根对象,因此可以直接访问。那么对于值栈中的对象该如何访问呢?Struts2提供了一个特殊的OGNLPropertyAccessor,它可以自动查找栈内的所有对象(从栈顶到栈底),直接找到一个具有你所查找的属性的对象。也就是说,对于值栈中的任何对象都可以直接访问,而不需要使用 “#”。
假设值栈中有两个对象:student和employee,两个对象都有name属性,student有学号属性number,而 employee有薪水属性salary。employee先入栈,student后入栈,位于栈顶,那么对于表达式name,访问的就是student 的name属性,因为student对象位于栈顶;表达式salary,访问的就是employee的salary属性。正如你所见,访问值栈中的对象属性或方法,无须指明对象,也不用“#”,就好像值栈中的对象都是OGNL上下文中的根对象一样。这就是Struts2在OGNL基础上做出的改进。
2、[N]语法
如上所述,如果想要访问employee的name属性,应该如何写表达式呢?我们可以使用[N].xxx(N是从0开始的整数)这样的语法来指定从哪一个位置开始向下查找对象的属性,表达式[1].name访问的就是employee对象的name属性。
在使用[N].xxx语法时,要注意位置序号的含义,它并不是表示“获取栈中索引为N的对象”,而是截取从位置N开始的部分栈。
3、top关键字
top用于获取栈顶的对象,结合[N].xxx语法,我们就可以获取栈中任意位置的对象。
如:[0].top,[1].top等
4、访问静态成员
除了使用标准的OGNL表达式访问静态字段和静态方法外,Struts2还允许你不指定完整的类名,而是通过“vs”前缀来调用保存在栈中的静态字段和静态方法。
@vs@FOO_PROPERTY
@vs@someMethod()
@vs1@someMethod()
vs表示ValueStack,如果只有vs,那么将使用栈顶对象的类;如果在vs后面跟上一个数字,那么将使用栈中指定位置处的对象类。
5、值栈中的Action实例
Struts2框架总是把Action实例放在栈顶。因为Action在值栈中,而值栈又是OGNL中的根,所以引用Action的属性可以省略“#”标记,这也是为什么我们在结果页面中可以直接访问Action的属性的原因。
6、Struts2中的命名对象
Struts2还提供了一些命名对象,这些对象没有保存在值栈中,而是保存在ActionContext中,因此访问这些对象需要使用“#”标记。这些命名对象都是Map类型。
parameters
用于访问请求参数。如:#parameters['id']或#parameters.id,相当于调用了HttpServletRequest对象的getParameter()方法。
注意,parameters本质上是一个使用HttpServletRequest对象中的请求参数构造的Map对象,一量对象被创建(在调用Action实例之前就已经创建好了),它和HttpServletRequest对象就没有了任何关系。
request
用于访问请求属性。如:#request['user']或#request.user,相当于调用了HttpServletRequest对象的getAttribute()方法。
session
用于访问session属性。如:#session['user']或#session.user,相当于调用了HttpSession对象的getAttribute()方法。
application
用于访问application属性。如:#application['user']或#application.user,相当于调用了ServletContext的getAttribute()方法。
attr
如果PageContext可用,则访问PageContext,否则依次搜索request、session和application对象。
PS:
在JSP 2.1 下 # 被加入了 JSP EL.中。这可能导致一些应用OGNL#号操作的程序出问题,下面是一种快速修复的方法是在web.xml中加上jsp-config的标签,这适用于一些支持JSP 2.1 EL表达式的容器,如GlassFish.
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>true</el-ignored>
</jsp-property-group>
</jsp-config>
struts中#、%和$这三个符号的使用方法
文章分类:Java编程
一、"#"的用法
1、访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:
parameters 包含当前HTTP请求参数的Map #parameters.id[0]作用相当于request.getParameter("id")
request 包含当前HttpServletRequest的属性(attribute)的Map #request.userName相当于request.getAttribute("userName")
session 包含当前HttpSession的属性(attribute)的Map #session.userName相当于session.getAttribute("userName")
application 包含当前应用的ServletContext的属性(attribute)的Map #application.userName相当于application.getAttribute("userName")
attr 用于按request > session > application顺序访问其属性(attribute)#attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止
2、用于过滤和投影(projecting)集合,如books.{?#this.price<100};
3、构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
二、"%"的用法
“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:
<h3>%的用途</h3>
<p><s:url value="#foobar['foo1']" /></p>
<p><s:url value="%{#foobar['foo1']}" /></p>
三、"$"的用法
1、用于在国际化资源文件中,引用OGNL表达式
2、在Struts 2配置文件中,引用OGNL表达式
例如:
<action name="AddPhoto" class="addPhoto">
<interceptor-ref name="fileUploadStack" />
<result type="redirect">ListPhotos.action? albumId=${albumId}</result>
</action>
分享到:
相关推荐
YOLOv12:以注意力为中心的实时目标检测器
GO语言基础语法指令教程
MATLAB代码实现:分布式电源接入对配电网运行影响深度分析与评估,MATLAB代码分析:分布式电源接入对配电网运行影响评估,MATLAB代码:分布式电源接入对配电网影响分析 关键词:分布式电源 配电网 评估 参考文档:《自写文档,联系我看》参考选址定容模型部分; 仿真平台:MATLAB 主要内容:代码主要做的是分布式电源接入场景下对配电网运行影响的分析,其中,可以自己设置分布式电源接入配电网的位置,接入配电网的有功功率以及无功功率的大小,通过牛顿拉夫逊法求解分布式电源接入后的电网潮流,从而评价分布式电源接入前后的电压、线路潮流等参数是否发生变化,评估配电网的运行方式。 代码非常精品,是研究含分布式电源接入的电网潮流计算的必备程序 ,分布式电源; 配电网; 接入影响分析; 潮流计算; 牛顿拉夫逊法; 电压评估; 必备程序。,基于MATLAB的分布式电源对配电网影响评估系统
三相光伏并网逆变器:Mppt最大功率跟踪与800V中间母线电压的电力转换技术,三相光伏并网逆变器:实现最大功率跟踪与800V中间母线电压的优化处理,三相光伏并网逆变器 输入光伏Mppt 最大功率跟踪中间母线电压800V 后级三相光伏并网逆变器 ,三相光伏并网逆变器; 输入光伏Mppt; 最大功率跟踪; 中间母线电压800V; 后级逆变器,三相光伏并网逆变器:MPPT最大功率跟踪800V母线电压
项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用
西门子博途三部十层电梯程序案例解析:基于Wincc RT Professional V14及更高版本的应用探索,西门子博途三部十层电梯程序案例解析:基于Wincc RT Professional画面与V14及以上版本技术参考,西门子1200博途三部十层电梯程序案例,加Wincc RT Professional画面三部十层电梯程序,版本V14及以上。 程序仅限于参考资料使用。 ,西门子;1200博途;三部十层电梯程序案例;Wincc RT Professional;V14以上程序版本。,西门子V14+博途三部十层电梯程序案例:Wincc RT Pro专业画面技术解析
基于舆情数据的知识图谱推荐可视化系统论文,全原创,免费分享
基于Vivado源码的AM包络检调制解调与FIR滤波器设计在FPGA上的实现,基于Zynq-7000和Artix-7系列的AM包络检调制解调源码及Vivado环境下的实现,AM包络检调制解调,Vivado源码 FPGA的AM调制解调源码,其中FIR滤波器根据MATLAB设计。 【AM_jietiao】文件是基于zynq-7000系列,但没有涉及AD与DA,只是单纯的仿真。 【AM包络检调制解调_Vivado源码】文件基于Artix-7系列,从AD读入信号后,进行AM调制,并解调DA输出。 ,AM包络检调制解调;Vivado源码;FPGA;AM调制解调源码;FIR滤波器;MATLAB设计;Zynq-7000系列;Artix-7系列;AD读入信号;DA输出,AM包络调制解调源码:Zynq-7000与Artix-7 FPGA的不同实现
yugy
2025山东大学:DeepSeek应用与部署(部署方案大全+API调用+业务应用)-80页.pptx
chromedriver-mac-x64-135.0.7023.0(Dev).zip
基于单片机protues仿真的433MHz无线模块编解码收发通信测试(仿真图、源代码) 该设计为单片机protues仿真的433MHz无线模块收发通信测试; 1、433M超再生收发模块; 2、在仿真图中是把发射MCU的P2_7腿直接输入到接收MCU的INT0实现编码解码的; 3、通过433MHz无线模块实现无线通信的编解码功能; 4、按键控制指令; 5、液晶屏显示收发状态和信息;
资源说说明; 自带文件管理 adb操作以及应用管理等等的功能。 操作性对比其他应用较好。 参阅博文: https://blog.csdn.net/mg668/article/details/145689511?spm=1001.2014.3001.5352
项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用
智慧图书管理系统(源码+数据库+论文)java开发springboot框架javaweb,可做计算机毕业设计或课程设计 【功能需求】 本系统分为读者、管理员2个角色 读者可以进行注册登录、浏览图书以及留言、图书借阅、图书归还、图书续借、个人中心、论坛交流、等功能 管理员可以进行读者管理、图书管理、论坛论坛回复管理、图书借阅管理(下架、库存管理、修改、删除)、轮播图管理 【环境需要】 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.数据库:MySql 5.7/8.0等版本均可; 【购买须知】 本源码项目经过严格的调试,项目已确保无误,可直接用于课程实训或毕业设计提交。里面都有配套的运行环境软件,讲解视频,部署视频教程,一应俱全,可以自己按照教程导入运行。附有论文参考,使学习者能够快速掌握系统设计和实现的核心技术。
三相APFC电路与单相Boost PFC电路仿真模型:电压外环电流内环双闭环控制研究,三相电路仿真模型:探索APFC电路、单相PFC电路及BoostPFC电路的动态特性与双闭环控制策略,APFC电路,单相PFC电路,单相BoostPFC电路仿真模型。 网侧220V 50Hz,输出电压设置为50Hz。 电压外环电流内环双闭环控制仿真模型 ,APFC电路; 单相PFC电路; 单相BoostPFC电路仿真模型; 网侧电压; 220V 50Hz; 输出电压50Hz; 电压外环电流内环双闭环控制仿真模型。,基于APFC电路的单相Boost PFC仿真模型:网侧电压220V/50Hz下电压电流双闭环控制的研究与应用
MATLAB环境下ADMM算法在分布式调度中的应用:比较并行与串行算法(Jocobi与Gaussian Seidel)的优化效果与实现细节——基于YALMIP和GUROBI的仿真平台复刻参考文档的研究结果。,MATLAB下ADMM算法在分布式调度中的并行与串行算法应用:基于YALMIP与GUROBI的仿真研究,MATLAB代码:ADMM算法在分布式调度中的应用 关键词:并行算法(Jocobi)和串行算法(Gaussian Seidel, GS) 参考文档:《主动配电网分布式无功优化控制方法》《基于串行和并行ADMM算法的电-气能量流分布式协同优化》 仿真平台:MATLAB YALMIP GUROBI 主要内容:ADMM算法在分布式调度中的应用 复刻参考文档 ,关键词:ADMM算法; 分布式调度; 并行算法(Jocobi); 串行算法(Gaussian Seidel, GS); MATLAB代码; YALMIP; GUROBI; 主动配电网; 无功优化控制方法; 能量流分布式协同优化。,MATLAB实现:ADMM算法在分布式调度中的并行与串行优化应用
“考虑P2G、碳捕集与碳交易机制的综合能源系统优化调度模型研究”,考虑电转气P2G与碳捕集设备的热电联供综合能源系统优化调度模型研究(含碳交易机制与四种算例场景分析),考虑P2G和碳捕集设备的热电联供综合能源系统优化调度模型 摘要:代码主要做的是一个考虑电转气P2G和碳捕集设备的热电联供综合能源系统优化调度模型,模型耦合CHP热电联产单元、电转气单元以及碳捕集单元,并重点考虑了碳交易机制,建立了综合能源系统运行优化模型,与目前市面上的代码不同,本代码完全复现了文档中所提出的四种算例场景,没有对比算例,买过去也没有任何意义,四种算例主要包括: 1)t不包括P2G、CCS、以及碳交易 2)t包括P2G,但是不包括CCS以及碳交易 3)t包括P2G和CCS,但是不包括碳交易 4)t包括P2G、CCS以及碳交易 且最终的实现效果与文档进行对比后,虽然数值无法100%一致,但是结果以及数值曲线,几乎完全一样,此版本为目前市面上最好的园区综合能源调度代码,没有之一 ,考虑电转气(P2G); 碳捕集设备; 热电联供综合能源系统; 优化调度模型; 碳交易机制; CHP热电联产单元; 耦合模型; 算
FS-LDM培训材料(DAY_2)_NCR数据仓库事业部.ppt
专题 平面向量的数量积(学生版)20250222.pdf