首先了解下
OGNL的概念
:
OGNL是
Object-Graph Navigation Language的缩写,全称为
对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者调用对象的方法,能够遍历整个对象的结构图,实现对象属性类型的转换等功能。
此外,还得先需弄懂OGNL的一些知识:
1.OGNL表达式的计算是围绕OGNL上下文进行的。
2.Struts2的标签库都是使用OGNL表达式来访问ActionContext中的对象数据的。如:<s:propertyvalue=”xxx”/>。
3.Struts2将ActionContext设置为OGNL上下文,并将值栈作为OGNL的根对象放置到ActionContext中。
4.值栈(ValueStack) :
5.调用ActionContext的put(key,value)放入的数据,需要使用#访问。
OGNL中重要的3个符号:#、%、$:
#、%和$符号在OGNL表达式中经常出现,而这三种符号也是开发者不容易掌握和理解的部分,需要时间的积累才渐渐弄清楚……
1.#符号
#符号的用途一般有三种。
— 访问非根对象属性,例如#session.msg表达式,由于Struts 2中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀。实际上,#相当于ActionContext. getContext();#session.msg表达式相当于ActionContext.getContext().getSession(). getAttribute(“msg”) 。
— 用于过滤和投影(projecting)集合,如persons.{?#this.age>25},persons.{?#this.name==’pla1′}.{age}[0]。
— 用来构造Map,例如示例中的#{‘foo1′:’bar1’, ‘foo2′:’bar2’}。
2.%符号
%符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值,这个类似js中的eval,很暴力。
3.$符号
$符号主要有两个方面的用途。
— 在国际化资源文件中,引用OGNL表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息:年龄必须在${min}同${max}之间。
— 在Struts 2框架的配置文件中引用OGNL表达式,例如:
-
<
validators
>
-
<
field
name
=
“intb”
>
-
<
field-validator
type
=
“int”
>
-
<
param
name
=
“min”
>
10
</
param
>
-
<
param
name
=
“max”
>
100
</
param
>
-
<
message
>
BAction-test校验:数字必须为${min}为${max}之间!
</
message
>
-
</
field-validator
>
-
</
field
>
-
</
validators
>
下面通过代码对OGNL有更深的了解:
action类OgnlAction.java:
-
package
com.tjcyjd.test.action;
-
-
import
java.util.Date;
-
import
java.util.LinkedList;
-
import
java.util.List;
-
-
import
javax.servlet.http.HttpServletRequest;
-
-
import
org.apache.struts2.ServletActionContext;
-
import
org.apache.struts2.convention.annotation.Action;
-
import
org.apache.struts2.convention.annotation.Namespace;
-
import
org.apache.struts2.convention.annotation.ParentPackage;
-
import
org.apache.struts2.convention.annotation.Result;
-
import
org.apache.struts2.convention.annotation.Results;
-
import
org.springframework.stereotype.Controller;
-
-
import
com.opensymphony.xwork2.ActionContext;
-
import
com.opensymphony.xwork2.ActionSupport;
-
-
@Controller
-
@Namespace
(
“/test”
)
-
@ParentPackage
(
“struts-default”
)
-
@Results
( {
@Result
(name =
“success”
, location =
“/other_test/showognl.jsp”
),
-
@Result
(name =
“fail”
, location =
“/bbs/admin_login.jsp”
),
-
@Result
(name =
“input”
, location =
“/bbs/admin_login.jsp”
) })
-
public
class
OgnlAction
extends
ActionSupport {
-
private
static
final
long
serialVersionUID = -1494290883433357310L;
-
private
List<Person> persons;
-
-
@Action
(
“ognlTest”
)
-
public
String ognlTest()
throws
Exception {
-
// 获得ActionContext实例,以便访问Servlet API
-
ActionContext ctx = ActionContext.getContext();
-
// 存入application
-
ctx.getApplication().put(
“msg”
,
“application信息”
);
-
// 保存session
-
ctx.getSession().put(
“msg”
,
“seesion信息”
);
-
// 保存request信息
-
HttpServletRequest request = ServletActionContext.getRequest();
-
request.setAttribute(
“msg”
,
“request信息”
);
-
// 为persons赋值
-
persons =
new
LinkedList<Person>();
-
Person person1 =
new
Person();
-
person1.setName(
“pla1”
);
-
person1.setAge(
26
);
-
person1.setBirthday(
new
Date());
-
persons.add(person1);
-
-
Person person2 =
new
Person();
-
person2.setName(
“pla2”
);
-
person2.setAge(
36
);
-
person2.setBirthday(
new
Date());
-
persons.add(person2);
-
-
Person person3 =
new
Person();
-
person3.setName(
“pla3”
);
-
person3.setAge(
16
);
-
person3.setBirthday(
new
Date());
-
persons.add(person3);
-
-
return
SUCCESS;
-
-
}
-
-
public
List<Person> getPersons() {
-
return
persons;
-
}
-
-
public
void
setPersons(List<Person> persons) {
-
this
.persons = persons;
-
}
-
}
jsp页面showognl.jsp:
-
<
%@ page
language
=
“java”
contentType
=
“text/html; charset=utf-8”
pageEncoding
=
“utf-8”
%
>
-
-
<
%@ taglib
prefix
=
“s”
uri
=
“/struts-tags”
%
>
-
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/ xhtml1/DTD/xhtml1-transitional.dtd”
>
-
-
<
html
xmlns
=
“http://www.w3.org/1999/xhtml”
>
-
-
<
head
>
-
-
<
title
>
Struts2 OGNL 演示
</
title
>
-
-
</
head
>
-
-
<
body
>
-
-
<
h3
>
访问OGNL上下文和Action上下文
</
h3
>
-
-
<!-使用OGNL访问属性值–
>
-
-
<
p
>
parameters:
<
s:property
value
=
“#parameters.msg”
/>
</
p
>
-
-
<
p
>
request.msg:
<
s:property
value
=
“#request.msg”
/>
</
p
>
-
-
<
p
>
session.msg:
<
s:property
value
=
“#session.msg”
/>
</
p
>
-
-
<
p
>
application.msg:
<
s:property
value
=
“#application.msg”
/>
</
p
>
-
-
<
p
>
attr.msg:
<
s:property
value
=
“#attr.msg”
/>
</
p
>
-
-
<
hr
/>
-
-
<
h3
>
用于过滤和投影(projecting)集合
</
h3
>
-
-
<
p
>
年龄大于20
</
p
>
-
-
<
ul
>
-
-
<!-判断年龄–
>
-
-
<
s:iterator
value
=
“persons.{?#this.age>20}”
>
-
-
<
li
>
<
s:property
value
=
“name”
/>
– 年龄:
<
s:property
value
=
“age”
/>
</
li
>
-
-
</
s:iterator
>
-
-
</
ul
>
-
-
<
p
>
姓名为pla1的年龄:
<
s:property
value
=
“persons.{?#this.name==’pla1′}.{age}[0]”
/>
</
p
>
-
-
<
hr
/>
-
-
<
h3
>
构造Map
</
h3
>
-
-
<
s:set
name
=
“foobar”
value
=
“#{‘foo1′:’bar1’, ‘foo2′:’bar2’}”
/>
-
-
<
p
>
The value of key “foo1” is
<
s:property
value
=
“#foobar[‘foo1’]”
/>
</
p
>
-
-
<
hr
/>
-
-
<
h4
>
%符号的用法
</
h4
>
-
-
<
s:set
name
=
“foobar”
value
=
“#{‘foo1′:’bar1’, ‘foo2′:’bar2’}”
/>
-
-
<
p
>
The value of key “foo1” is
<
s:property
value
=
“#foobar[‘foo1’]”
/>
</
p
>
-
-
<
p
>
不使用%:
<
s:url
value
=
“#foobar[‘foo1’]”
/>
</
p
>
-
-
<
p
>
使用%:
<
s:url
value
=
“%{#foobar[‘foo1’]}”
/>
</
p
>
-
-
<
hr
/>
-
<
%
-
request.setAttribute(“req”, “request scope”);
-
request.getSession().setAttribute(“sess”, “session scope”);
-
request.getSession().getServletContext().setAttribute(“app”,
-
“aplication scope”);
-
%
>
-
1.通过ognl表达式获取 属性范围中的值
-
<
br
>
-
<
s:property
value
=
“#request.req”
/>
-
<
br
/>
-
<
s:property
value
=
“#session.sess”
/>
-
<
br
/>
-
<
s:property
value
=
“#application.app”
/>
-
<
br
/>
-
<
hr
>
-
-
2.通过
<
span
style
=
“background-color: #fafafa;”
>
ognl表达式创建list 集合 ,并且遍历出集合中的值
-
<
br
>
-
<
s:set
name
=
“list”
value
=
“{‘eeeee’,’ddddd’,’ccccc’,’bbbbb’,’aaaaa’}”
>
</
s:set
>
-
<
s:iterator
value
=
“#list”
var
=
“o”
>
-
<!– ${o }<br/> –>
-
<
s:property
/>
-
<
br
/>
-
</
s:iterator
>
-
<
br
/>
-
<
hr
>
-
-
3.通过ognl表达式创建Map 集合 ,并且遍历出集合中的值
-
<
br
>
-
<
s:set
name
=
“map”
-
value
=
“#{‘1′:’eeeee’,’2′:’ddddd’,’3′:’ccccc’,’4′:’bbbbb’,’5′:’aaaaa’}”
>
</
s:set
>
-
<
s:iterator
value
=
“#map”
var
=
“o”
>
-
<!– ${o.key }->${o.value }<br/> –>
-
<!– <s:property value=”#o.key”/>-><s:property value=”#o.value”/><br/> –>
-
<
s:property
value
=
“key”
/>
–
>
<
s:property
value
=
“value”
/>
-
<
br
/>
-
</
s:iterator
>
-
<
br
/>
-
<
hr
>
-
4.通过ognl表达式 进行逻辑判断
-
<
br
>
-
<
s:if
test
=
“‘aa’ in {‘aaa’,’bbb’}”
>
-
aa 在 集合{‘aaa’,’bbb’}中;
-
</
s:if
>
-
<
s:else
>
-
aa 不在 集合{‘aaa’,’bbb’}中;
-
</
s:else
>
-
<
br
/>
-
<
s:if
test
=
“#request.req not in #list”
>
-
不 在 集合list中;
-
</
s:if
>
-
<
s:else
>
-
在 集合list中;
-
</
s:else
>
-
<
br
/>
-
<
hr
>
-
-
5.通过ognl表达式 的投影功能进行数据筛选
-
<
br
>
-
<
s:set
name
=
“list1”
value
=
“{1,2,3,4,5}”
>
</
s:set
>
-
<
s:iterator
value
=
“#list1.{?#this>2}”
var
=
“o”
>
-
<!– #list.{?#this>2}:在list1集合迭代的时候,从中筛选出当前迭代对象>2的集合进行显示 –>
-
${o }
<
br
/>
-
</
s:iterator
>
-
<
br
/>
-
<
hr
>
-
6.通过ognl表达式 访问某个类的静态方法和值
-
<
br
>
-
<
s:property
value
=
“@java.lang.Math@floor(32.56)”
/>
-
-
<
s:property
value
=
“@com.rao.struts2.action.OGNL1Action@aa”
/>
-
<
br
/>
-
<
br
/>
-
<
hr
>
-
7.ognl表达式 迭代标签 详细
-
<
br
>
-
<
s:set
name
=
“list2”
-
value
=
“{‘aa’,’bb’,’cc’,’dd’,’ee’,’ff’,’gg’,’hh’,’ii’,’jj’}”
>
</
s:set
>
-
<
table
border
=
“1”
>
-
<
tr
>
-
<
td
>
索引
</
td
>
-
<
td
>
值
</
td
>
-
<
td
>
奇?
</
td
>
-
<
td
>
偶?
</
td
>
-
<
td
>
首?
</
td
>
-
<
td
>
尾?
</
td
>
-
<
td
>
当前迭代数量
</
td
>
-
</
tr
>
-
<
s:iterator
value
=
“#list2”
var
=
“o”
status
=
“s”
>
-
<
tr
bgcolor
=
“<s:if test=”
#s.even”
>
pink
</
s:if
>
”
>
-
<
td
>
-
<
s:property
value
=
“#s.getIndex()”
/>
-
</
td
>
-
<
td
>
-
<
s:property
/>
-
</
td
>
-
<
td
>
-
<
s:if
test
=
“#s.odd”
>
Y
</
s:if
>
-
<
s:else
>
N
</
s:else
>
-
</
td
>
-
<
td
>
-
<
s:if
test
=
“#s.even”
>
Y
</
s:if
>
-
<
s:else
>
N
</
s:else
>
-
</
td
>
-
<
td
>
-
<
s:if
test
=
“#s.first”
>
Y
</
s:if
>
-
<
s:else
>
N
</
s:else
>
-
</
td
>
-
<
td
>
-
<
s:if
test
=
“#s.isLast()”
>
Y
</
s:if
>
-
<
s:else
>
N
</
s:else
>
-
</
td
>
-
<
td
>
-
<
s:property
value
=
“#s.getCount()”
/>
-
</
td
>
-
</
tr
>
-
</
s:iterator
>
-
</
table
>
-
<
br
>
-
<
hr
>
-
-
-
8.ognl表达式: if/else if/else 详细
<
br
>
-
<
% request.setAttribute(“aa”,0); %
>
-
<
s:if
test
=
“#request.aa>=0 && #request.aa<=4”
>
-
在0-4之间;
-
</
s:if
>
-
<
s:elseif
test
=
“#request.aa>=4 && #request.aa<=8”
>
-
在4-8之间;
-
</
s:elseif
>
-
<
s:else
>
-
大于8;
-
</
s:else
>
-
<
br
>
-
<
hr
>
-
9.ognl表达式: url 详细
<
br
>
-
<
% request.setAttribute(“aa”,”sss”); %
>
-
<
s:url
action
=
“testAction”
namespace
=
“/aa/bb”
>
-
<
s:param
name
=
“aa”
value
=
“#request.aa”
>
</
s:param
>
-
<
s:param
name
=
“id”
>
100
</
s:param
>
-
</
s:url
>
-
<
br
/>
-
<
s:set
name
=
“myurl”
value
=
“‘http://www.baidu.com'”
>
</
s:set
>
-
value以字符处理:
<
s:url
value
=
“#myurl”
>
</
s:url
>
<
br
>
-
value明确指定以ognl表达式处理:
<
s:url
value
=
“%{#myurl}”
>
</
s:url
>
-
<
br
>
-
<
hr
>
-
10.ognl表达式: checkboxlist 详细
<
br
>
-
1
>
.list 生成;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<
br
>
-
name:checkboxlist的名字
<
br
>
-
list:checkboxlist要显示的列表
<
br
>
-
value:checkboxlist默认被选中的选项,
checked
checked
=checked
<
br
>
-
<
s:checkboxlist
name
=
“checkbox1”
list
=
“{‘上网’,’看书’,’爬山’,’游泳’,’唱歌’}”
value
=
“{‘上网’,’看书’}”
>
</
s:checkboxlist
>
-
<
br
>
-
以上生成代码:
<
br
>
-
<
xmp
>
-
<
input
type
=
“checkbox”
name
=
“checkbox1”
value
=
“上网”
id
=
“checkbox1-1”
checked
=
“checked”
/>
-
<
label
for
=
“checkbox1-1”
class
=
“checkboxLabel”
>
上网
</
label
>
-
<
input
type
=
“checkbox”
name
=
“checkbox1”
value
=
“看书”
id
=
“checkbox1-2”
checked
=
“checked”
/>
-
<
label
for
=
“checkbox1-2”
class
=
“checkboxLabel”
>
看书
</
label
>
-
<
input
type
=
“checkbox”
name
=
“checkbox1”
value
=
“爬山”
id
=
“checkbox1-3”
/>
-
<
label
for
=
“checkbox1-3”
class
=
“checkboxLabel”
>
爬山
</
label
>
-
<
input
type
=
“checkbox”
name
=
“checkbox1”
value
=
“游泳”
id
=
“checkbox1-4”
/>
-
<
label
for
=
“checkbox1-4”
class
=
“checkboxLabel”
>
游泳
</
label
>
-
<
input
type
=
“checkbox”
name
=
“checkbox1”
value
=
“唱歌”
id
=
“checkbox1-5”
/>
-
<
label
for
=
“checkbox1-5”
class
=
“checkboxLabel”
>
唱歌
</
label
>
”
-
</
xmp
>
-
2
>
.Map 生成;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<
br
>
-
name:checkboxlist的名字
<
br
>
-
list:checkboxlist要显示的列表
<
br
>
-
listKey:checkbox 的value的值
<
br
>
-
listValue:checkbox 的lablel(显示的值)
<
br
>
-
value:checkboxlist默认被选中的选项,
checked
checked
=checked
<
br
>
-
<
s:checkboxlist
name
=
“checkbox2”
list
=
“#{1:’上网’,2:’看书’,3:’爬山’,4:’游泳’,5:’唱歌’}”
listKey
=
“key”
listValue
=
“value”
value
=
“{1,2,5}”
>
</
s:checkboxlist
>
-
<
br
>
-
以上生成代码:
<
br
>
-
<
xmp
>
-
<
input
type
=
“checkbox”
name
=
“checkbox2”
value
=
“1”
id
=
“checkbox2-1”
checked
=
“checked”
/>
-
<
label
for
=
“checkbox2-1”
class
=
“checkboxLabel”
>
上网
</
label
>
-
<
input
type
=
“checkbox”
name
=
“checkbox2”
value
=
“2”
id
=
“checkbox2-2”
checked
=
“checked”
/>
-
<
label
for
=
“checkbox2-2”
class
=
“checkboxLabel”
>
看书
</
label
>
-
<
input
type
=
“checkbox”
name
=
“checkbox2”
value
=
“3”
id
=
“checkbox2-3”
/>
-
<
label
for
=
“checkbox2-3”
class
=
“checkboxLabel”
>
爬山
</
label
>
-
<
input
type
=
“checkbox”
name
=
“checkbox2”
value
=
“4”
id
=
“checkbox2-4”
/>
-
<
label
for
=
“checkbox2-4”
class
=
“checkboxLabel”
>
游泳
</
label
>
-
<
input
type
=
“checkbox”
name
=
“checkbox2”
value
=
“5”
id
=
“checkbox2-5”
checked
=
“checked”
/>
-
<
label
for
=
“checkbox2-5”
class
=
“checkboxLabel”
>
唱歌
</
label
>
-
</
xmp
>
-
<
hr
>
-
</
body
>
-
</
html
>
总结OGNL的使用方法:
访问属性
名字属性获取:<s:property value=”user.username”/><br> 地址属性获取:<s:property value=”user.address.addr”/><br> |
访问方法
调用值栈中对象的普通方法:<s:property value=”user.get()”/><br> |
访问静态属性和方法
调用Action中的静态方法:<s:property value=”@struts.action.LoginAction@get()”/> 调用JDK中的类的静态方法:<s:property value=”@java.lang.Math@floor(44.56)”/><br> 调用JDK中的类的静态方法(同上):<s:property value=”@@floor(44.56)”/><br> 调用JDK中的类的静态方法:<s:property value=”@java.util.Calendar@getInstance()”/><br> 调用普通类中的静态属性:<s:property value=”@struts.vo.Address@TIPS”/><br> |
访问构造方法
调用普通类的构造方法:<s:property value=”new struts.vo.Student(‘李晓红’ , ‘美女’ , 3 , 25).username”/>
|
1.5. 访问数组
获取List:<s:property value=”testList”/><br> 获取List中的某一个元素(可以使用类似于数组中的下标获取List中的内容): <s:property value=”testList[0]”/><br> 获取Set:<s:property value=”testSet”/><br> 获取Set中的某一个元素(Set由于没有顺序,所以不能使用下标获取数据): <s:property value=”testSet[0]”/><br> × 获取Map:<s:property value=”testMap”/><br> 获取Map中所有的键:<s:property value=”testMap.keys”/><br> 获取Map中所有的值:<s:property value=”testMap.values”/><br> 获取Map中的某一个元素(可以使用类似于数组中的下标获取List中的内容): <s:property value=”testMap[‘m1’]”/><br> 获取List的大小:<s:property value=”testSet.size”/><br> |
访问集合 – 投影、选择(? ^ $)
利用选择获取List中成绩及格的对象:<s:property value=”stus.{?#this.grade>=60}”/><br> 利用选择获取List中成绩及格的对象的username: <s:property value=”stus.{?#this.grade>=60}.{username}”/><br> 利用选择获取List中成绩及格的第一个对象的username: <s:property value=”stus.{?#this.grade>=60}.{username}[0]”/><br> 利用选择获取List中成绩及格的第一个对象的username: <s:property value=”stus.{^#this.grade>=60}.{username}”/><br> 利用选择获取List中成绩及格的最后一个对象的username: <s:property value=”stus.{$#this.grade>=60}.{username}”/><br> 利用选择获取List中成绩及格的第一个对象然后求大小: <s:property value=”stus.{^#this.grade>=600}.{username}.size”/><br> |
集合的伪属性
OGNL能够引用集合的一些特殊的属性,这些属性并不是JavaBeans模式,例如size(),length()等等. 当表达式引用这些属性时,OGNL会调用相应的方法,这就是伪属性.
集合 |
伪属性 |
Collection(inherited by Map, List & Set) |
size ,isEmpty |
List |
iterator |
Map |
keys , values |
Set |
iterator |
Iterator |
next , hasNext |
Enumeration |
next , hasNext , nextElement , hasMoreElements |
Lambda :[…]
格式::[…]
使用Lambda表达式计算阶乘: <s:property value=”#f = :[#this==1?1:#this*#f(#this-1)] , #f(4)”/><br> |
OGNL中#的使用
#可以取出堆栈上下文中的存放的对象.
名称 |
作用 |
例子 |
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) |
|
获取Paraments对象的属性:<s:property value=”#parameters.username”/>
OGNL中%的使用
用%{}可以取出存在值堆栈中的Action对象,直接调用它的方法.
例如你的Action如果继承了ActionSupport .那么在页面标签中,用%{getText(‘key’)}的方式可以拿出国际化信息.
OGNL中$的使用
“$”有两个主要的用途
l 用于在国际化资源文件中,引用OGNL表达式
l 在Struts 2配置文件中,引用OGNL表达式
值栈
ValueStack对象。这个对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当 Struts 2接收到一个.action的请求后,会先建立Action类的对象实例,但并不会调用Action方法,而是先将Action类的相应属性放到 ValueStack对象的顶层节点(ValueStack对象相当于一个栈)。
在Action中获得ValueStack对象:ActionContext.getContext().getValueStack()
l Top语法
使用Top获取值栈中的第二个对象:<s:property value=”[1].top.对象”/>
l N语法
使用N获取值栈中的第二个对象:<s:property value=”[1].对象”/>
l @语法
调用action中的静态方法:<s:property value=”@vs1@静态方法”/> vs:值栈 1:表示第一个。