8.1.2  OGNL语法
基本的OGNL语法是十分简单的,当然OGNL支持丰富的表达式,一般情况下,不用担心OGNL的复杂性。例如有一个man对象,该对象有一个name属性,那么使用OGNL来获得该name属性可以使用如下表达式:
man.name
OGNL表达式的基础单元称为导航链,简称为链。一个最简单的链由如下部分组成。
 
属性名称:如上述示例中的name
 
方法调用:hashCode()返回当前对象的hash code
 
数组元素:listeners[0]返回当前对象的列表中的第一个元素。
说明
OGNL表达式基于OGNL上下文中的当前对象,一个将使用上一个的处理结果,开发者可以任意扩展该链的长度,OGNL没有限制。
例如,一个OGNL表达式如下:
CharArray()[0].String() 

该表达式将按照如下步骤求值。
1)获得OGNL Context中初始对象或者是根对象(root对象)的name对象。
2)调用toCharArray()方法,返回一个String类型对象。
3)获得该String对象的第一个字符。
4)获得该字符的numericValue属性(该字符为一个Character对象,该对象有一个getNumericValue()方法,该方法返回一个Integer类型值)。
5)将获得的Integer对象转换为一个String类型值(使用toString()方法)。
8.1.3  一个使用OGNL的示例
下面笔者以一个简单的示例来帮助读者理解OGNL表达式。使用OGNL表达式,需要在网站下载一个ognl.jar插件包,将该文件复制到classpath路径下即可。建立一个复合类型,如代码8.1所示。
代码8.1  定义复合类型
package ch8;
import java.util.Date;
//团队类
public class Team {
// 团队名称
private String teamname;
// 定义团队人员属性
private Person person;
// 团队人数
private int personnum;
//属性的gettersetter方法
public String getTeamname() {
return teamname;
}
public void setTeamname(String teamname) {
amname = teamname;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public int getPersonnum() {
return personnum;
}
public void setPersonnum(int personnum) {
this.personnum = personnum;
}
}
// 定义人员类
class Person {
// 姓名
private String name;
// 年龄
private int age;
// 人员出生日期
private Date birthday;
//属性的gettersetter方法
public String getName() {
return name;
}
public  void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
代码8.1所示内容定义了两个复合类型:团队(team)和人员(person)类型。使用OGNL表达式示例,如代码8.2所示。
代码8.2  使用OGNL表达式示例
package ch8;
import java.util.HashMap;
import java.util.Map;
import ognl.Ognl;
import ognl.OgnlException;
public class TestOGNL {
public static void main(String[] args) {
//定义一个Map对象
Map m = new HashMap();
//定义一个Team对象
Team team1 = new Team();
team1.setTeamname("团队1");
//定义一个Person对象
Person person1 = new Person();
person1.setName("pla1");
//添加team元素
team1.setPerson(person1);
//定义一个Team对象
Team team2 = new Team();
team2.setTeamname("团队2");
//定义一个Person对象
Person person2 = new Person();
person2.setName("pla2");
//添加team元素
team2.setPerson(person2);

//添加Map元素
m.put("team1", team1);
m.put("team2", team2);
try {
System.out.Value("amname", m));
System.out.Value("team2.person.name", m));
System.out.Value("teamname", team2));
System.out.Value("person.name", team2));
} catch (OgnlException e) {
}
}
}

代码8.2所示内容定义了一个Map类型的嵌套属性,如图8.1所示。
 
8.1  嵌套属性示意图
运行该示例,控制器显示如下信息:
团队1
pla2
团队2
pla2
说明
OGNL可以使用非常简单的表达式来访问多层嵌套属性,为开发者提供了一个有力的工具。
8.2  Struts 2OGNL
OGNLStruts 2框架的默认表达式语言,增强了Struts 2的数据访问能力,同时简化了代码。
8.2.1  Struts 2OGNL表达式
标准的OGNL会设定一个根对象(root对象)。假设使用标准OGNL表达式来求值(不使用Struts 2OGNL表达式),如果OGNL上下文(OgnlContext Map类型)有两个对象:foo对象,在OgnlContext中名称为foobar对象,在OgnlContext中名称为bar。同时foo对象被设置为根对象(root)。则利用下面的OGNL表达式求值:
// 返回Blah()
#foo.blah
//返回Blah()
#bar.blah
//返回Blah() ,因为foo为根对象
blah
说明
使用OGNL是非常简单的,如果要访问的对象不是根对象,如示例中的bar对象,则需要使用命名空间,用#”来标识,如#bar”;如果访问一个根对象,则不用指定命名空间,可以直接访问根对象的属性。
Struts 2框架中,值栈(Value Stack)就是OGNL的根对象,假设值栈中存在两个对对象实例:ManAnimal,这两个对象实例都有一个name属性,Animal有一个species属性,Man有一个salary属性,假设Animal在值栈的顶部,ManAnimal后面,下面的代码片断会帮助读者更好地理解OGNL表达式:
// 调用Species()
species
// 调用Salary()
salary
// 调用Name(),因为Animal位于值栈的顶部
name
getattribute方法返回类型

最后一行示例代码,返回的是Name()返回值,即返回了Animalname属性,因为Animal是值栈的顶部元素,OGNL将从顶部元素搜索,所以会返回Animalname属性值。如果要获得Manname值,则需要如下代码:
man.name
Struts 2允许在值栈中使用索引,示例代码如下所示:
[0].name  // 调用Name()
[1].name  // 调用Name()
注意
使用索引,并不是直接获得指定的元素,而是从指定的索引位置搜索。
Struts 2中的OGNL ContextActionContext,如图8.2所示。
 
8.2  Struts 2OGNL Context结构示意图
说明
8.2只是说明Struts 2OGNL Context结构,实际上Context还包含其他对象。
由于值栈是Struts 2OGNL的根对象,如果用户需要访问值栈中的对象,则可以直接通过下面的代码访问值栈中的属性:
//获得值栈中的foo属性
${foo}
如果访问其他Context中的对象,由于不是根对象,在访问时,需要加#前缀。
 
application对象:用于访问ServletContext,例如#application.userName或者#application['userName'],相当于调用ServletgetAttribute("username")
 
session对象:用来访问HttpSession,例如#session.userName或者#session['userName'],相当于调用Attribute("userName")
 
request对象:用来访问HttpServletRequest属性(attribute)的Map,例如#request.userName或者#request['userName'],相当于调用Attribute ("userName")
 
parameters对象:用于访问HTTP的请求参数,例如#parameters.userName或者#parameters['userName'],相当于调用Parameter("username")
 
attr对象:用于按page-request-session-application顺序访问其属性。
8.2.2  OGNL的集合操作
如果需要一个集合元素的时候(例如List对象或者Map对象),可以使用OGNL中同集合相关的表达式。
可以使用如下代码直接生成一个List对象:
{e1,e2,e3}
OGNL表达式中,直接生成了一个List对象,该List对象中包含3个元素:e1e2e3。如果需要更多的元素,可以按照这样的格式定义多个元素,多个元素之间使用逗号隔开。
如下代码可以直接生成一个Map对象:
#{key1:value1,key2:value2,}

Map类型的集合对象,使用key-value格式定义,每个key-value元素使用冒号标识,多个元素之间使用逗号隔开。
对于集合类型,OGNL表达式可以使用innot in两个元素符号。其中,in表达式用来判断某个元素是否在指定的集合对象中;not in判断某个元素是否不在指定的集合对象中,如代码8.3所示。
代码8.3  使用OGNL集合操作符
 
muhahaha


boo

muhahaha


boo
除了innot in之外,OGNL还允许使用某个规则获得集合对象的子集,常用的有以下3个相关操作符。
 
?:获得所有符合逻辑的元素。
 
^:获得符合逻辑的第一个元素。
 
$:获得符合逻辑的最后一个元素。
例如代码:
latives.{? #der == 'male'}
该代码可以获得person的所有性别为malerelatievs集合。
8.2.3  Lambda表达式
OGNL支持基本的Lambda表达式语法,通过Lambda表达式语法,可以在OGNL中使用一些简单的函数。例如:
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
开发者可以使用Lambda表达式语法:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。