OGNL

OGNL

 

OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。

 

 

 

基本介绍

 

OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。这样可以更好的取得数据。

 

OGNL可以让我们用非常简单的表达式访问对象层,例如,当前环境的根对象为user1,则表达式person.address[0].province可以访问到user1的person属性的第一个address的province属性。

 

这种功能是模板语言的一个重要补充,像jsp2.0,velocity,jelly等等,都有类似的功能,但是ognl比它们完善得多,而且以一个独立的lib出现,方便我们构建自己的框架。

 

webwork2和现在的Struts2.x中使用OGNL取代原来的EL来做界面数据绑定,所谓界面数据绑定,也就是把界面元素(例如一个textfield,hidden)和对象层某个类的某个属性绑定在一起,修改和显示自动同步。

 

和struts1.x的formbean相比,这样做的好处非常明显:在webwork中不需要为每个页面专门写formbean,可以直接利用对象层的对象。例如在对象设计中,我们的User和Person是分开的,而一个注册用户界面需要填写两者的内容,在webwork中,就可以保持后台的对象结构,把属于用户属性的界面元素用user.person.xxx绑定,把属于账号属性的界面元素用user.xxx绑定。

 

Struts 2

 

OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言,使页面更简洁;

 

支持运算符(如+-*/),比普通的标志具有更高的自由度和更强的功能;

 

Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:

 

支持对象方法调用,如xxx.doSomeSpecial();

 

支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;

 

支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(price*discount),这个表达式会返回80;

 

访问OGNL上下文(OGNL context)和ActionContext;

 

操作集合对象。

 

可以直接new一个对象

 

用法

 

OGNL是通常要结合Struts 2的标志一起使用。主要是#、%和$这三个符号的使用。使用方法如下:

 

新建名为Struts2_OGNL的Web工程

 

#”主要有三种用途:

 

访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性: 名称 作用 例子

 

parameters 包含当前HTTP请求参数的Map #parameters.id[0]作用相当于request.getParameterValues("id").get(0);

 

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属性,直到找到为止

 

用于过滤和投影(projecting)集合,如books.{?#this.price<100};

 

构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。

 

下面让我们它们的具体写法,首先是Action类代码:

 

package tutorial.action;

 

import java.util.LinkedList;

 

import java.util.List;

 

import java.util.Map;

 

import javax.servlet.ServletContext;

 

import javax.servlet.http.HttpServletRequest;

 

import org.apache.struts2.interceptor.ServletRequestAware;

 

import org.apache.struts2.interceptor.SessionAware;

 

import org.apache.struts2.util.ServletContextAware;

 

import tutorial.model.Book;

 

import com.opensymphony.xwork2.ActionSupport;

 

public class OgnlAction extends ActionSupport implements ServletRequestAware, SessionAware, ServletContextAware {

 

private static final long serialVersionUID = 1L;

 

private HttpServletRequest request;

 

private Map session;

 

private ServletContext application;

 

private List books;

 

public void setServletRequest(HttpServletRequest request) {

 

this.request = request;

 

}

 

@SuppressWarnings("unchecked")

 

public void setSession(Map session) {

 

this.session = session;

 

}

 

public void setServletContext(ServletContext application) {

 

this.application = application;

 

}

 

public List getBooks() {

 

return books;

 

}

 

@Override

 

public String execute() {

 

request.setAttribute("userName", "Max From request");

 

session.put("userName", "Max From session");

 

application.setAttribute("userName", "Max From application");

 

books = new LinkedList();

 

books.add(new Book("978 0735619678", "Code Complete, Second Edition", 32.99));

 

books.add(new Book("978 0596007867", "The Art of Project Management", 35.96));

 

books.add(new Book("978 0201633610", "Design Patterns: Elements of Reusable Object-Oriented Software", 43.19));

 

books.add(new Book("978 0596527341", "Information Architecture for the World Wide Web: Designing Large-Scale Web Sites", 25.19));

 

books.add(new Book("978 0735605350", "Software Estimation: Demystifying the Black Art", 25.19));

 

return SUCCESS;

 

}

 

}

 

以上代码分别在request、session和application的范围内添加“userName”属性,然后再在JSP页面使用OGNL将其取回。

 

下面是Ognl.jsp的代码,内容如下:

 

访问OGNL上下文和Action上下文

 

parameters.userName:

 

request.userName:

 

session.userName:

 

application.userName:

 

attr.userName:

 

用于过滤和投影(projecting)集合

 

Books more than $35

 

<s:iterator value="books.{?#this.price > 35}">

 

<s:property value="title" /> - $<s:property value="price" /><br>

 

</s:iterator>

 

The price of "Code Complete, Second Edition" is:

 

构造Map

 

The value of key "foo1" is

 

清单3 WebContent/Ognl.jsp 以上代码值得注意的是“”,因为“books.{?#this.title=='Code Complete, Second Edition'}.{price}”返回的值是集合类型,所以要用“[索引]”来访问其值。 最后是Struts 2的配置文件struts.xml,内容如下:

 

/Ognl.jsp

 

“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。

 

“$”有两个主要的用途,用于在国际化资源文件中,引用OGNL表达式。在Struts 2和i18n中配置文件

 

 

 

发音

 

We pronounce OGNL as a word, like the last syllables of a drunken pronunciation of "orthogonal."

 

表达式

 

OGNL支持各种纷繁复杂的表达式。但是最最基本的表达式的原型,是将对象的引用值用点串联起来,从左到右,每一次表达式计算返回的结果成为当前对象,后面部分接着在当前对象上进行计算,一直到全部表达式计算完成,返回最后得到的对象。OGNL则针对这条基本原则进行不断的扩充,从而使之支持对象树、数组、容器的访问,甚至是类似SQL中的投影选择等操作。

 

1. 基本对象树的访问

 

对象树的访问就是通过使用点号将对象的引用串联起来进行。

 

例如:xxxx,xxxx.xxxx,xxxx. xxxx. xxxx. xxxx. xxxx

 

2. 对容器变量的访问

 

对容器变量的访问,通过#符号加上表达式进行。

 

例如:#xxxx,#xxxx. xxxx,#xxxx.xxxxx. xxxx. xxxx. xxxx

 

3. 使用操作符号

 

OGNL表达式中能使用的操作符基本跟Java里的操作符一样,除了能使用 +, -, *, /, ++, --, ==, !=, = 等操作符之外,还能使用 mod, in, not in等。

 

4. 容器、数组、对象

 

OGNL支持对数组和ArrayList等容器的顺序访问:例如:group.users[0]

 

同时,OGNL支持对Map的按键值查找:

 

例如:#session['mySessionPropKey']

 

不仅如此,OGNL还支持容器的构造的表达式:

 

例如:{"green", "red", "blue"}构造一个List,#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}构造一个Map

 

你也可以通过任意类对象的构造函数进行对象新建:

 

例如:new Java.net.URL("xxxxxx/")

 

5. 对静态方法或变量的访问

 

要引用类的静态方法和字段,他们的表达方式是一样的@class@member或者@class@method(args):

 

例如:@com.javaeye.core.Resource@ENABLE,@com.javaeye.core.Resource@getAllResources

 

6. 方法调用

 

直接通过类似Java的方法调用方式进行,你甚至可以传递参数:

 

例如:user.getName(),group.users.size(),group.containsUser(#requestUser)

 

7. 投影和选择

 

OGNL支持类似数据库中的投影(projection) 和选择(selection)。

 

投影就是选出集合中每个元素的相同属性组成新的集合,类似于关系数据库的字段操作。投影操作语法为 collection.{XXX},其中XXX 是这个集合中每个元素的公共属性。

 

例如:group.userList.{username}将获得某个group中的所有user的name的列表。

 

选择就是过滤满足selection 条件的集合元素,类似于关系数据库的纪录操作。选择操作的语法为:collection.{X YYY},其中X 是一个选择操作符,后面则是选择用的逻辑表达式。而选择操作符有三种:

 

? 选择满足条件的所有元素

 

^ 选择满足条件的第一个元素

 

$ 选择满足条件的最后一个元素

 

例如:group.userList.{? #txxx.xxx != null}将获得某个group中user的name不为空的user的列表。

 

posted @ 2019-04-19 17:19  滤v镜  阅读(326)  评论(0编辑  收藏  举报