启天论坛软件硬件技术Java技术 → OGNL,简单的struts 2专用表达式


  共有223人关注过本帖树形打印

主题:OGNL,简单的struts 2专用表达式

帅哥哟,离线,有人找我吗?
junsan
  1楼 个性首页 | QQ | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信 总掌门
等级:管理员 帖子:11764 积分:7955 威望:757 精华:24 注册:2005-7-14 15:13:00
OGNL,简单的struts 2专用表达式  发帖心情 Post By:2008-9-6 13:03:00



OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,OGNL是一个开源项目,读者可以访问其官方站点www.ognl.org以获得源代码和相关资料。OGNL是一种功能强大的EL(Expression Language,表达式语言),可以通过简单的表达式来访问Java对象中的属性。

OGNL先在WebWork项目中得到应用,也是Struts 2框架视图默认的表达式语言,可以说,OGNL表达式是Struts 2框架的特点之一。

下面笔者以一个简单的示例来帮助读者理解OGNL表达式。使用OGNL表达式,需要在www.ognl.org网站下载一个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;
    //属性的getter和setter方法
    public String getTeamname() {
        return teamname;
    }
    public void setTeamname(String teamname) {
        this.teamname = 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;
    //属性的getter和setter方法
    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.println(Ognl.getValue("team1.teamname", m));
            System.out.println(Ognl.getValue("team2.person.name", m));
            System.out.println(Ognl.getValue("teamname", team2));
            System.out.println(Ognl.getValue("person.name", team2));
        } catch (OgnlException e) {
        }
    }
}
代码8.2所示内容定义了一个Map类型的嵌套属性,如图8.1所示。


图8.1  嵌套属性示意图
运行该示例,控制器显示如下信息:
团队1
pla2
团队2
pla2
★ 说明 ★
OGNL可以使用非常简单的表达式来访问多层嵌套属性,为开发者提供了一个有力的工具。
 
8.2  Struts 2的OGNL OGNL是Struts 2框架的默认表达式语言,增强了Struts 2的数据访问能力,同时简化了代码。


主页:http://www.rsky.com.cn

培训论坛:http://www.javastar.org

Blog:http://blog.csdn.net/junnef

技术交流QQ:334620162

培训咨询QQ:66883074

合租咨询QQ:631066985

MSN:junsanjin@hotmail.com

Emial:junsanjin@263.net

传真:(010)950507转747393
启天合组-10人 15人 20人 多人合租空间 支持(0中立(0反对(0回到顶部
帅哥哟,离线,有人找我吗?
junsan
  2楼 个性首页 | QQ | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信 总掌门
等级:管理员 帖子:11764 积分:7955 威望:757 精华:24 注册:2005-7-14 15:13:00
  发帖心情 Post By:2008-9-6 13:10:00

标准的OGNL会设定一个根对象(root对象)。假设使用标准OGNL表达式来求值(不使用Struts 2的OGNL表达式),如果OGNL上下文(OgnlContext Map类型)有两个对象:foo对象,在OgnlContext中名称为foo;bar对象,在OgnlContext中名称为bar。同时foo对象被设置为根对象(root)。则利用下面的OGNL表达式求值:
// 返回foo.getBlah()
#foo.blah
//返回bar.getBlah()
#bar.blah
//返回foo.getBlah() ,因为foo为根对象
blah
★ 说明 ★
使用OGNL是非常简单的,如果要访问的对象不是根对象,如示例中的bar对象,则需要使用命名空间,用“#”来标识,如“#bar”;如果访问一个根对象,则不用指定命名空间,可以直接访问根对象的属性。
 
在Struts 2框架中,值栈(Value Stack)就是OGNL的根对象,假设值栈中存在两个对对象实例:Man和Animal,这两个对象实例都有一个name属性,Animal有一个species属性,Man有一个salary属性,假设Animal在值栈的顶部,Man在Animal后面,下面的代码片断会帮助读者更好地理解OGNL表达式:
// 调用animal.getSpecies()
species
// 调用man.getSalary()
salary
// 调用animal.getName(),因为Animal位于值栈的顶部
name
最后一行示例代码,返回的是animal.getName()返回值,即返回了Animal的name属性,因为Animal是值栈的顶部元素,OGNL将从顶部元素搜索,所以会返回Animal的name属性值。如果要获得Man的name值,则需要如下代码:
man.name
Struts 2允许在值栈中使用索引,示例代码如下所示:
[0].name   // 调用animal.getName()
[1].name   // 调用man.getName()
★ 说明 ★
使用索引,并不是直接获得指定的元素,而是从指定的索引位置搜索。
 
Struts 2中的OGNL Context是ActionContext,如图8.2所示。
图片点击可在新窗口打开查看

图8.2  Struts 2的OGNL Context结构示意图
★ 说明 ★
图8.2只是说明Struts 2的OGNL Context结构,实际上Context还包含其他对象。
 
由于值栈是Struts 2中OGNL的根对象,如果用户需要访问值栈中的对象,则可以直接通过下面的代码访问值栈中的属性:
//获得值栈中的foo属性
${foo}
如果访问其他Context中的对象,由于不是根对象,在访问时,需要加#前缀。
? application对象:用于访问ServletContext,例如#application.userName或者#application['userName'],相当于调用Servlet的getAttribute("username")。
? session对象:用来访问HttpSession,例如#session.userName或者#session['userName'],相当于调用session.getAttribute("userName")。
? request对象:用来访问HttpServletRequest属性(attribute)的Map,例如#request.userName或者#request['userName'],相当于调用request.getAttribute("userName")。
? parameters对象:用于访问HTTP的请求参数,例如#parameters.userName或者#parameters['userName'],相当于调用request.getParameter("username")。
? attr对象:用于按page-request-session-application顺序访问其属性。


主页:http://www.rsky.com.cn

培训论坛:http://www.javastar.org

Blog:http://blog.csdn.net/junnef

技术交流QQ:334620162

培训咨询QQ:66883074

合租咨询QQ:631066985

MSN:junsanjin@hotmail.com

Emial:junsanjin@263.net

传真:(010)950507转747393
启天合组-专业合租空间提供商 支持(0中立(0反对(0回到顶部
帅哥哟,离线,有人找我吗?
junsan
  3楼 个性首页 | QQ | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信 总掌门
等级:管理员 帖子:11764 积分:7955 威望:757 精华:24 注册:2005-7-14 15:13:00
  发帖心情 Post By:2008-9-6 13:10:00

如果需要一个集合元素的时候(例如List对象或者Map对象),可以使用OGNL中同集合相关的表达式。
可以使用如下代码直接生成一个List对象:
{e1,e2,e3…}
该OGNL表达式中,直接生成了一个List对象,该List对象中包含3个元素:e1、e2和e3。如果需要更多的元素,可以按照这样的格式定义多个元素,多个元素之间使用逗号隔开。
如下代码可以直接生成一个Map对象:
#{key1:value1,key2:value2,…}
Map类型的集合对象,使用key-value格式定义,每个key-value元素使用冒号标识,多个元素之间使用逗号隔开。
对于集合类型,OGNL表达式可以使用in和not in两个元素符号。其中,in表达式用来判断某个元素是否在指定的集合对象中;not in判断某个元素是否不在指定的集合对象中,如代码8.3所示。
代码8.3  使用OGNL集合操作符
<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>
除了in和not in之外,OGNL还允许使用某个规则获得集合对象的子集,常用的有以下3个相关操作符。
? ?:获得所有符合逻辑的元素。
? ^:获得符合逻辑的第一个元素。
? $:获得符合逻辑的最后一个元素。
例如代码:
person.relatives.{? #this.gender == 'male'}
该代码可以获得person的所有性别为male的relatievs集合。


主页:http://www.rsky.com.cn

培训论坛:http://www.javastar.org

Blog:http://blog.csdn.net/junnef

技术交流QQ:334620162

培训咨询QQ:66883074

合租咨询QQ:631066985

MSN:junsanjin@hotmail.com

Emial:junsanjin@263.net

传真:(010)950507转747393
启天合组-上海双线 上海电信 南京电信空间 支持(0中立(0反对(0回到顶部
帅哥哟,离线,有人找我吗?
junsan
  4楼 个性首页 | QQ | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信 总掌门
等级:管理员 帖子:11764 积分:7955 威望:757 精华:24 注册:2005-7-14 15:13:00
  发帖心情 Post By:2008-9-6 13:11:00

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表达式语法:
<s:property value="#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" />


主页:http://www.rsky.com.cn

培训论坛:http://www.javastar.org

Blog:http://blog.csdn.net/junnef

技术交流QQ:334620162

培训咨询QQ:66883074

合租咨询QQ:631066985

MSN:junsanjin@hotmail.com

Emial:junsanjin@263.net

传真:(010)950507转747393
启天合组-10人 15人 20人 多人合租空间 支持(0中立(0反对(0回到顶部