版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/huangbin10025/article/details/24910849
OGNL
OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言(Expression Language,简称为EL),通过它简单一致的表达式语法,能够存取对象的随意属性。调用对象的方法,遍历整个对象的结构图。实现字段类型转化等功能。它使用同样的表达式去存取对象的属性。
OGNL是Object-Graph Navigation Language的缩写。它是一种功能强大的表达式语言(Expression Language,简称为EL),通过它简单一致的表达式语法。能够存取对象的随意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用同样的表达式去存取对象的属性。
这样能够更好的取得数据。
OGNL能够让我们用很easy的表达式訪问对象层。比如,当前环境的根对象为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绑定。
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.getParameter("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中配置文件
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/")
要引用类的静态方法和字段,他们的表达方式是一样的@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的列表。