

金剑
发布于2009年10月31日
OGNL最初旨在能够使用对象的属性名称在UI组件和控制器之间建立连接. 简而言之: 视图和控制器之间的数据连接. 后来,为了应对更复杂的数据关系,Drew Davidson发明了一种称为KVCL(键值编码语言)的语言. 卢克(Luke)参加之后,他使用ANTLR来实现该语言并为其赋予了新的名称. 后来他使用JavaCC重新实现了该语言. 目前OGNL由Drew维护. 目前,OGNL已用于许多项目中,其中许多都是众所周知的项目,例如几个流行的Web应用程序框架: WebWork,Tapestry等.
OGNL是对象图导航语言的缩写. 从语言角度来看: 它是一种功能强大的表达语言,用于获取和设置Java对象的属性. 它旨在提供更高的抽象语法来导航Java对象图,OGNL在许多地方都有应用程序,例如:
作为GUI元素(文本字段,组合框等)用于建模对象的绑定语言. 从表到Swing TableModel的数据源语言. Web组件和后端模型对象(WebOGNL,Tapestry,WebWork,WebObjects)的绑定语言. 作为Jakarata Commons BeanUtils或JSTL表达语言的一种更具表现力的替代语言.
此外,还可以使用OGNL完成许多Java中可以完成的事情,例如: 列表映射和选择. 对于开发人员,使用OGNL,您可以使用简单的语法来完成Java对象的导航. 一般而言: 要通过“路径”完成对象信息的导航,此“路径”可以是java Bean的属性,也可以是集合中的索引对象等,而不是直接使用get或set方法来完成
表达式语言(EL)实质上旨在帮助您使用简单表达式来完成一些“常用”任务. 通常,EL可以在某些框架中找到,用于简化我们的工作. 例如: 著名的Hibernate使用HQL(休眠查询语言)来完成操作. HQL已成为开发人员和所审查的SQL表达式之间的桥梁. 在Web框架中,表达语言具有相似的目的. 它的存在消除了重复代码的编写. 例如: 当没有EL时,为了从会话中获取购物车并在网页上显示IDognl map,当直接使用Java代码在jsp中完成时,通常是:
<%
ShoppingCart cart = (ShoppingCart) session.get("cart");
int id = cart.getId();
%>
<%= id%>
您还可以将这些代码压缩为一个句子,如下所示,但是现在代码非常不直观且不可读. 另外,尽管它变成了一个句子,但它包含的表达式与上面的原始示例相同. 例如: 类型转换: 转换为ShoppingCart. 这只是将原来的三个表达式变成一个句子,其复杂性并没有得到简化.

<%= ((ShoppingCart) session.get("cart")).getId() %>
在Web框架中使用表达语言时,可以有效地处理此代码的复杂性. 没有您,请调用servelet API,进行类型转换,然后调用getter方法. 大多数Els可以将此过程简化为以下形式: #session.cart.id这是一个更具可读性的表达式. 表达式: #session.cart.id与Java代码不同: 没有get方法调用和Java代码的类型转换. 由于这些操作非常“常见”,因此此时使用EL是合乎逻辑的. 使用EL可以“消除”这些代码.
OGNL表达式通常非常简单. 尽管OGNL语言本身已经变得更加丰富和强大,但通常来说,那些更复杂的语言功能并未影响OGNL的简单性: 简单的部分仍然如此简单. 例如,要获取对象的name属性,则OGNL表达式为name,而要获取对象的headline属性的text属性,则OGNL表达式为headline.text. OGNL表达的基本单位是“导航链”,通常简称为“链”. 最简单的链包含以下部分:
表达成分示例
属性名称
作为上面示例中的名称和标题文本
方法调用
hashCode()返回当前对象的哈希码.
数组元素
listeners [0]返回当前对象的侦听器列表中的第一个元素.

所有OGNL表达式都基于当前对象的上下文进行评估,并且链的前一部分的结果将用作后续评估的上下文. 您的连锁店可能会很长,例如:
name.toCharArray()[0].numericValue.toString()
上述表达式的评估步骤:
以上示例仅用于获取对象的值,OGNL也可以用于设置对象的值. 将上面的表达式传递给Ognl.setValue()方法将导致InappropriateExpressionException,因为链的最后一部分(toString())既不是属性的名称也不是数组的元素. 知道以上语法即可基本完成大部分工作.
OGNL不仅可以获取或设置对象的属性,还可以用于完成实例方法的调用,静态方法的调用,表达式求值,Lambda表达式等. 让我们看看如何使用OGNL完成这些任务.
最简单的用法是直接使用ognl.Ognl类来评估OGNL表达式. Ognl类提供了一些静态方法来解析和解释OGNL表达式. 最简单的示例是在不使用上下文的情况下从对象获取表达式的值. 示例如下:
import ognl.Ognl; import ognl.OgnlException;
try {
result = Ognl.getValue(expression, root);
}
catch (OgnlException ex)
{ // Report error or recover }
上面的代码将基于根对象评估表达式并返回结果. 如果表达式错误,例如,找不到指定的属性,则将引发OgnlException. 一个更复杂的应用程序是使用预先解析的表达式. 此方法允许在评估表达式之前捕获表达式分析错误. 应用程序开发人员可以缓存表达式解析结果(AST),当反复使用时可以提高性能. Ognl的parseExpression方法用于执行预解析操作. 在Ognl 2.7版本之后,由于添加了“表达式编译”,该性能在质量上得到了提高,这将在后面的章节中介绍. 获取和设置Ognl类的方法还可以接受上下文映射参数,该参数允许您放置一些自己的变量,并且可以在Ognl表达式中使用. 默认上下文仅包含#root和#context键. 下面的示例演示如何从根对象中解析documentName属性,然后在返回结果之后添加当前用户名:
private Map context = new HashMap();
public void setUserName(String value)
{
context.put("userName", value);
}
try {
// get value using our own custom context map
result = Ognl.getValue("userName"", context, root);
} catch (OgnlException ex) {
// Report error or recover
}
上面提到的#root变量指向当前的根变量(用于表达式评估的初始对象),而#context是指向的Map对象. 以下示例可以更直观地说明

User root = new User();
root.setId(19612);
root.setName("sakura");
Map context = new HashMap();
context.put("who", "Who am i?");
try {
String who1 = (String)Ognl.getValue("#who", context, root);
String who2 = (String)Ognl.getValue("#context.who", context, root);
Object whoExp = Ognl.parseExpression("#who");
String who3 = (String)Ognl.getValue(whoExp, context, root);
//who1 who2 who3 返回同样的值, whoExp 重复使用可以提高效率
String name1 = (String)Ognl.getValue("name", root);
String name2 = (String)Ognl.getValue("#root.name", root);
//name1 name2 返回同样的值
} catch (OgnlException e) {
//error handling
}
常量: 字符串: “ hello”字符: 'h'数字: 除了Java,int,long,float和double,Ognl等内置类型外,还有一个示例: 10.01B,它等效对于java.math.BigDecimal,请使用'b'或'B'后缀. 100000H,等效于java.math.BigInteger,使用后缀'h'或'H'属性参考示例: user.name变量参考示例: #name使用@ class @字段的静态变量访问使用@ class @方法的静态方法调用( args),如果未指定类,则默认使用java.lang.Math. 调用构造函数示例: new java.util.ArrayList();
有关其他Ognl表达式,请参阅Ognl语言手册.
我们之前已经介绍过的OGNL API,OGNL的主要功能之一是对象图的导航. 让我们看一下OGNL的最基本的API来获取值和设置
public static java.lang.Object getValue(java.lang.String expression,
java.util.Map context,
java.lang.Object root,
java.lang.Class resultType)
throws OgnlException
Evaluates the given OGNL expression to extract a value
from the given root object in a given context
Parameters:
expression - the OGNL expression to be parsed
context - the naming context for the evaluation
root - the root object for the OGNL expression
resultType - the converted type of the resultant object,
using the context's type converter
Returns:
the result of evaluating the expression
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-225969-1.html