一、ognl表达式定义:
OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言(Expression Language,简称为EL),通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。
二、ognl表达式的优势:
Struts 2默认的表达式语言是OGNL,他有一下几大优势:
1、支持对象方法调用,形式如:objName.methodName();
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(都指的是action上下文); #xxxx,#xxxx. xxxx,#xxxx.xxxxx. xxxx. xxxx. xxxx
5、操作集合对象。
6、OGNL表达式中能使用的操作符基本跟Java里的操作符一样,除了能使用 +, -, *, /, ++, --, ==, !=, = 等操作符之外,还能使用 mod, in, not in等。(引号内)
三、ognl表达式的用法:
OGNL要结合struts标签来使用。由于比较灵活,也容易把人给弄晕,尤其是“%”、“#”、“$”这三个符号的使用。由于$广泛应用于EL中,这里重点写%和#符号的用法。
注意:对于struts标签取action值栈中的属性(根对象中的属性),是不需要加任何前缀符号的
1、“#”符号有三种用途:
(1)、访问非根对象(struts中值栈为根对象)ognlContext=actionContext,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:
名称 作用 例子
parameters 包含当前HTTP请求参数的Map #parameters.id[0]作用相当于request.getParameter("id")
request 包含当前HttpServletRequest的属性(attribute)的Map #request.userName相当于request.getAttribute("userName")
session 包含当前HttpSession的属性的Map #session.userName相当于session.getAttribute("userName")
application 包含当前应用的ServletContext的属性的Map #application.userName相当于application.getAttribute("userName")
attr 用于按request> session > application顺序访问属性 #attr.userName相当于按顺序在以上三个范围内读取userName属性,直到找到为止
(2)、用于过滤和投影(projecting)集合,
如:books.{?#this.price>35}
books.{?#this.title=='Code Complete, Second Edition'}[0].price
books.{?#this.title=='Code Complete, SecondEdition'}.{price}[0],因为books.{?#this.title=='Code Complete, Second Edition'}.{price}返回的类型为集合
其中:? 选择满足条件的所有元素
^ 选择满足条件的第一个元素
$ 选择满足条件的最后一个元素
(3)、构造Map,如:#{'foo1':'bar1','foo2':'bar2'} 这种方式常用在给radio或select、checkbox等标签赋值上。
如果要在页面中取一个map的值可以这样写: <s:property value="#myMap['foo1']"/>
2、“%”符号的用途是在标签的属性值被理解为字符串类型时,告诉执行环境%{}里的字符串是OGNL表达式。 有点类似javascript里面的eval_r()功能,
例如 : var oDiv = eval_r("2+4”);alert(oDiv);弹出的则是6,就是把认为的字符串作为表达式进行处理 的
举例:
<s:set name="myMap"value="#{'key1':'value1','key2':'value2'}"/>
<s:property value="#myMap['key1']"/>
<s:url value="#myMap['key1']"/>
上面的代码第2行会在页面上输出“value1”,而第3行则会输出"#myMap['key1']"这么一个字符串。如果将第3行改写成这样:
<s:url value="%{#myMap['key1']}"/>
则输出为“value1”。
3、“$”有两种用途
(1)、在国际化资源文件中,引用OGNL表达式。
(2)、在Struts2配置文件中,引用OGNL表达式:
例如:
<action name="saveUser"class="userAction"method="save">
<result type="redirect">listUser.action?msg=${msg}</result>
</action>
四、列举实例:
1、访问值栈中的普通属性(对应set/get方法):<s:property value="username"/>
2、访问值栈中对象的普通属性(get set方法):<s:property value="user.age"/>| <s:propertyvalue="user['age']"/>
3、访问action上下文中的对象的属性:<s:propertyvalue="#session.user.age"/>
4、访问值栈中对象的普通方法:<s:propertyvalue="cat.miaomiao()" /
5、 访问值栈中action的普通方法:<s:property value="actionMethod()" />
6、访问静态方法和属性:
在Struts.xml中<constantname="struts.ognl.allowStaticMethodAccess"value="true"></constant>
a、访问静态方法:<s:propertyvalue="@com.bjsxt.struts2.ognl.S@s()"/>
b、 访问静态属性:<s:propertyvalue="@com.bjsxt.struts2.ognl.S@STR"/>
c、 访问Math类的静态方法:<s:property value="@@max(2,3)" />
7、访问构造方法:
访问普通类的构造方法:<s:propertyvalue="newcom.bjsxt.struts2.ognl.User(8)"/>
8、访问list:
a、访问List:<s:property value="users"/>
b、访问List中某个元素:<s:propertyvalue="users[1]"/>
c、访问List中元素某个属性的集合:<s:propertyvalue="users.{age}"/>
d、访问List中元素某个属性的集合中的特定值:<s:propertyvalue="users.{age}[0]"/>
或者 <s:propertyvalue="users[0].age"/>
9、访问map:
a、访问Map:<s:property value="dogMap"/>
b、访问Map中某个元素:<s:propertyvalue="dogMap.dog"/>
<s:propertyvalue="dogMap['dog']"/>
<s:propertyvalue="dogMap[\"dog\"]"/>
c、访问Map中所有的key:<s:propertyvalue="dogMap.keys"/>
d、访问Map中所有的value:<s:propertyvalue="dogMap.values"/>
e、访问容器的大小:<s:property value="dogMap.size()"/>
10、过滤和投影集合:
a、投影(过滤):<s:propertyvalue="users.{?#this.age==1}[0]"/>
遍历USERS集合,然后取出来集合里面age==1的第一个元素
b、投影:<s:property value="users.{^#this.age>1}.{age}"/> ^表示开头的,取出开头age>1的那个user的age
c、 投影:<s:propertyvalue="users.{$#this.age>1}.{age}"/> $表示结尾的,取出结尾age>1的那个user的age
d、投影:<s:property value="users.{$#this.age>1}.{age} ==null"/>
11、自定义变量:
a、设值:<s:setvar="adminName" value="username" />(默认为request)
取值: <s:property value="#adminName"/>或者<s:propertyvalue="#request.adminName"/>
指定session设值:<s:set var="adminPassword"value="password"scope="session"/>
取值:<s:propertyvalue="#adminPassword"/>或者<s:propertyvalue="#session.adminPassword"/>
b、list集合形式:
<s:iteratorvalue="{'aaa', 'bbb', 'ccc'}"var="x">
<s:propertyvalue="#x.toUpperCase()"/>|
</s:iterator>
使用status:
<s:iteratorvalue="{'aaa', 'bbb', 'ccc'}"status="status">
<s:property/> |
遍历过的元素总数:<s:property value="#status.count"/> |
遍历过的元素索引:<s:property value="#status.index"/> |
当前是偶数?:<s:property value="#status.even"/> |
当前是奇数?:<s:property value="#status.odd"/>|
是第一个元素吗?:<s:property value="#status.first"/> |
是最后一个元素吗?:<s:property value="#status.last"/>
</s:iterator>
下面这种处理List。这个代码在页面上建立一个下拉选项,内容是list中的内容,默认值是name2.
<s:select label="label"name="name" list="{'name1','name2','name3'}"value="%{'name2'}" />
c、map集合形式:必须加#{}
<s:iteratorvalue="#{1:'a', 2:'b', 3:'c'}">
<s:propertyvalue="key"/> |<s:property value="value"/> <br/>
</s:iterator>
<s:iteratorvalue="#{1:'a', 2:'b', 3:'c'}"var="x">
<s:propertyvalue="#x.key"/> |<s:property value="#x.value"/><br />
</s:iterator>
下面这种处理Map:
<s:select label="label"name="name" list="#{'foo':'foovalue', 'bar':'barvalue'}"/>
需要注意的是,判断一个值是否在collection中。我们要使用in或者not in来处理。
<s:if test="'foo' in{'foo','bar'}">
</s:if>
<s:else>
boo
</s:else>
12、在struts标签if/else中使用:
age =<s:propertyvalue="#parameters.age[0]" /> <br />
<s:setvar="age"value="#parameters.age[0]" />
利用set标签把#parameters.age[0]改成age这样简化代码
<s:if test="#age <0">wrongage!</s:if>
<s:elseif test="#parameters.age[0] <20">too young!</s:elseif>
<s:else>yeah!</s:else><br/>
<s:iftest="#parameters.aaa ==null">null</s:if>