- 浏览: 1504809 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (798)
- struts2 (42)
- servlet (20)
- quartz (4)
- jquery & ajax (24)
- tomcat (5)
- javascript (15)
- struts1 (8)
- 搜索关键字及链接 (3)
- fckeditor (3)
- Apache (5)
- spring (22)
- linux (3)
- 企业应用 (8)
- 综合应用 (13)
- 服务器 (2)
- 数据库 (85)
- 性能调优 (21)
- 网络应用 (15)
- 缓存技术 (8)
- 设计模式 (39)
- 面试题 (7)
- 程序人生&前辈程序员 (29)
- java基础 (59)
- hibernate (75)
- log4j (4)
- http (11)
- 架构设计 (28)
- 网页设计 (12)
- java邮件 (4)
- 相关工具 (11)
- ognl (7)
- 工作笔记 (18)
- 知识面扩展 (12)
- oracle异常 (1)
- 正则表达式 (2)
- java异常 (5)
- 项目实践&管理 (1)
- 专业术语 (11)
- 网站参考 (1)
- 论坛话题 (2)
- web应用 (11)
- cxf&webservice (22)
- freemarker (3)
- 开源项目 (9)
- eos (1)
- ibatis (6)
- 自定义标签 (3)
- jsp (3)
- 内部非公开文档(注意:保存为草稿) (0)
- 国内外知名企业 (2)
- 网店 (3)
- 分页 (1)
- 消费者习惯 (2)
- 每日关注 (1)
- 商业信息 (18)
- 关注商业网站 (1)
- 生活常识 (3)
- 新闻 (2)
- xml&JSON (5)
- solaris (1)
- apache.common (3)
- BLOB/CLOB (1)
- lucene (2)
- JMS (14)
- 社会进程 (8)
- SSH扩展 (2)
- 消费心理 (1)
- 珠三角 (1)
- 设计文档 (1)
- XWork&webwork (1)
- 软件工程 (3)
- 数据库及链接 (1)
- RMI (2)
- 国内外知名企业&人物 (1)
最新评论
-
司c马:
简介易懂、
OutputStream和InputStream的区别 -
在世界的中心呼喚愛:
解决我的问题
Java获取客户端的真实IP地址 -
bo_hai:
都是些基本的概念呀!
SSO -
tian_4238:
哥们,你也是搞水利这块的吧。
巧用SQLQuery中的addScalar -
loveEVERYday:
java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp小结
OGNL 最初是为了能够使用对象的属性名来建立 UI 组件 (component) 和 控制器 (controllers) 之间的联系,简单来说就是:视图 与 控制器 之间数据的联系。后来为了应付更加复杂的数据关系,Drew Davidson 发明了一个被他称为 KVCL(Key-Value Coding Language) 的语言。 Luke 参与进来后,用 ANTLR 来实现了该语言,并给它取了这个新名字,他后来又使用 JavaCC 重新实现了该语言。目前 OGNL 由 Drew 来负责维护。目前很多项目中都用到了 OGNL,其中不乏为大家所熟知的,例如几个流行的 web 应用框架:WebWork,Tapestry 等。
OGNL 是 Object-Graph Navigation Language 的缩写,从语言角度来说:它是一个功能强大的表达式语言,用来获取和设置 java 对象的属性 , 它旨在提供一个更高抽象度语法来对 java 对象图进行导航,OGNL 在许多的地方都有应用,例如:
- 作为 GUI 元素(textfield,combobox, 等)到模型对象的绑定语言。
- 数据库表到 Swing 的 TableModel 的数据源语言。
- web 组件和后台 Model 对象的绑定语言 (WebOGNL,Tapestry,WebWork,WebObjects) 。
- 作为 Jakarata Commons BeanUtils 或者 JSTL 的表达式语言的一个更具表达力的替代语言。
另外,java 中很多可以做的事情,也可以使用 OGNL 来完成,例如:列表映射和选择。对于开发者来说,使用 OGNL,可以用简洁的语法来完成对 java 对象的导航。通常来说:通过一个“路径”来完成对象信息的导航,这个“路径”可以是到 java bean 的某个属性,或者集合中的某个索引的对象,等等,而不是直接使用 get 或者 set 方法来完成。
表达式语言(EL)本质上被设计为:帮助你使用简单的表达式来完成一些“常用”的工作。通常情况下,ELs 可以在一些框架中找到,它被是用来简化我们的工作。例如:大家熟知的 Hibernate,使用 HQL(Hibernate Query Language) 来完成数据库的操作,HQL 成了开发人员与复查的 SQL 表达式之间的一个桥梁。在 web 框架下,表达式语言起到了相似的目的。它的存在消除了重复代码的书写。例如:当没有 EL 的时候,为了从 session 中得到购物车并且将 ID 在网页上呈现出来,当直接在 jsp 中使用 java 代码来完成的时候,一般是:
<% ShoppingCart cart = (ShoppingCart) session.get("cart"); int id = cart.getId(); %> <%= id%> |
你也可以将这些 code 压缩成一句,如下,但是现在代码就很不直观,且不可读。另外,虽然变成了一句,但是与上面的原始的例子一样,也包含了同样的表达式。例如:类型转换:转换成 ShoppingCart 。这里只不过是将原来的三个表达式变成了一句,其复杂度是没有得到简化的。
<%= ((ShoppingCart) session.get("cart")).getId() %> |
当在 web 框架中使用表达式语言的时候,则可以有效的处理这种代码的复杂性。而不需要你,调用 servelet API,类型转换,然后再调用 getter 方法,多数的 Els 都可将这个过程简化为类似于:#session.cart.id 这中更可读的表达式。表达式:#session.cart.id 与 java 代码不一样的是:没有 java 代码的 get 方法调用和类型转换。因为这些操作是非常“常用”的,这时候使用 EL 就顺理成章了,使用 EL 可以“消除”这些代码。
OGNL 表达式一般都很简单。虽然 OGNL 语言本身已经变得更加丰富了也更强大了,但是一般来说那些比较复杂的语言特性并未影响到 OGNL 的简洁:简单的部分还是依然那么简单。比如要获取一个对象的 name 属性,OGNL 表达式就是 name, 要获取一个对象的 headline 属性的 text 属性,OGNL 表达式就是 headline.text 。 OGNL 表达式的基本单位是“导航链”,往往简称为“链”。最简单的链包含如下部分:
如上述示例中的 name 和 headline.text |
hashCode() 返回当前对象的哈希码。 |
listeners[0] 返回当前对象的监听器列表中的第一个元素。 |
所有的 OGNL 表达式都基于当前对象的上下文来完成求值运算,链的前面部分的结果将作为后面求值的上下文。你的链可以写得很长,例如:
name.toCharArray()[0].numericValue.toString() |
上面的表达式的求值步骤:
- 提取根 (root) 对象的 name 属性。
- 调用上一步返回的结果字符串的 toCharArray() 方法。
- 提取返回的结果数组的第一个字符。
- 获取字符的 numericValue 属性,该字符是一个 Character 对象,Character 类有一个 getNumericValue() 方法。
- 调用结果 Integer 对象的 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 } |
上述代码将基于 root 对象评估 expression,返回结果,如果表达式有错,比如没有找到指定的属性,将抛出 OgnlException 。更复杂一点的应用是使用预解析的表达式。这种方式允许在表达式求值之前就能捕获表达式的解析错误,应用开发人员可以缓存表达式解析出来的结果(AST),从而能在重复使用的时候提高性能。 Ognl 的 parseExpression 方法就是用来执行预解析操作的。 Ognl 2.7 版本后由于添加了“ Expression Compilation ”性能得到了质的提高,在后面章节会有介绍。 Ognl 类的获取和设置方法也可以接受一个 context map 参数,他允许你放一些自己的变量,并能在 Ognl 表达式中使用。缺省的上下文里只包含 #root 和 #context 两个键。下面的示例展示如何从 root 对象中解析出 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 变量指向的就是当前的 root 变量(表达式求值的初始对象(initial object)), 而 #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@field
- 静态方法的调用使用 @class@method(args), 如果没有指定 class 那么默认就使用 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 |
public static void setValue(java.lang.String expression, java.util.Map context, java.lang.Object root, java.lang.Object value) throws OgnlException Evaluates the given OGNL expression to insert a value into the object graph rooted at the given root object given the context. Parameters: expression - the OGNL expression to be parsed root - the root object for the OGNL expression context - the naming context for the evaluation value - the value to insert into the object graph |
OGNL 的 API 设计得是很简单的,context 提供上下文,为变量和表达式的求值过程来提供命名空间,存储变量 等,通过 root 来指定对象图遍历的初始变量,使用 expression 来告诉 Ognl 如何完成运算。看看下面两个简单的代码片段:\
User user1 = new User(); user1.setId(1); user1.setName("firer"); User user2 = new User(); user2.setId(2); user2.setName("firer2"); List users = new ArrayList(); users.add(user1); users.add(user2); Department dep = new Department(); dep.setUsers(users); dep.setName("dep"); dep.setId(11); Object o = Ognl.getValue("users[1].name", dep); |
这里我们可以看到前面介绍的使用表达式语言的有点,使用 "users[1].name",就能完成对 name 的取值,而不用去进行类型转换等工作。下面是一个简单的设值的例子。
User user = new User(); user.setId(1); user.setName("ffirer"); Ognl.setValue("department.name", user, "dep1"); |
就想前面介绍的,Ognl 也可以完成一些其它的工作,一个例子就是在我们的日常工作中,我们经常需要从列表中去“搜索”符合我们要求的对象,使用 java 的时候我们需要对列表进行遍历、类型转换、取值然后比较来得到我们想要的值,而使用 Ognl 将使这个过程变得简单,优雅。代码片段:
User user1 = new User(); user1.setId(1); user1.setName("firer"); // 如上例创建一些 User List users = new ArrayList(); users.add(user1); // 将创建的 User 添加到 List 中 Department dep = new Department(); dep.setUsers(users); List names = (List)Ognl.getValue("users.{name}", dep); List ids = (List)Ognl.getValue("users.{? #this.id > 1}", dep); |
这里表达式 "users.{name}" 将取得列表中所有 Users 的 name 属性,并以另外一个列表返回。 "users.{? #this.id > 1}" 将返回所有 id 大于 1 的 User,也以一个列表返回,包含了所有的 User 对象。这里使用的是 Ognl 的“列表投影”操作,叫这个名字是因为比较像数据库中返回某些列的操作。 Ognl 还有很多其它功能,在 Ognl 的 SVN(http://svn.opensymphony.com/svn/ognl/trunk)的 testcase 中找到如何使用它们。
OGNL,或者说表达式语言的性能主要又两方面来决定,一个就是对表达式的解析 (Parser),另一个是表达式的执行,OGNL 采用 javaCC 来完成 parser 的实现,在 OGNL 2.7 中又对 OGNL 的执行部分进行了加强,使用 javasisit 来 JIT(Just-In-Time) 的生成 byte code 来完成表达式的执行。 Ognl 给这个功能的名字是:OGNL Expression Compilation 。基本的使用方法是:
SimpleObject root = new SimpleObject(); OgnlContext context = (OgnlContext) Ognl.createDefaultContext(null); Node node = (Node) Ognl.compileExpression(context, root, "user.name"); String userName = (String)node.getAccessor().get(context, root); |
那么使用 Expression Compilation 能给 Ognl 的性能带来什么了?一个性能方面的简单测试:对比了 4 中情况:分别是:直接 Java 调用 (1), OGNL 缓存使用 expression compilation (2), OGNL 缓存使用 OGNL expression parsed(3) 以及不使用任何缓存的结果(4)。
可以看到 expression compilation 非常接近使用 java 调用的时间,所以可以看到当表达式要被多次使用,使用 expression compilation 并且已经做好了缓存的情况下,OGNL 非常接近 java 直接调用的时间。
本文介绍了 OGNL 的概念、表达式语法以及如何使用 OGNL, 并提供了一些简单的示例代码,OGNL 在实际应用中还可以对其进行扩展,在本文中并为涉及, 感兴趣的读者可以进一步进行相关的学习和研究
<!-- CMA ID: 442385 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->
学习
讨论
- 查看 OGNL 用户论坛。
发表评论
-
Struts2 ognl中的#、%和$符号用法说明
2011-02-28 17:27 1391#、%和$符号在OGNL表达式中经常出现,而这三种符号也是开发 ... -
Struts2.1 OGNL 表达式 学习笔记
2011-02-28 17:22 1111<%@ page language="j ... -
Struts2 OGNL中的投影(过滤)
2011-02-28 17:14 1696Struts2 OGNL中的投影(过滤) <s:pro ... -
Struts 2中的OGNL
2011-02-25 10:00 1729本人是一个EL(Expression Language,以下译 ... -
OGNL使用小结
2010-11-11 10:41 1273OGNL使用小结(一)最近一 ... -
EL跟OGNL对比
2010-08-06 14:06 6460取Session中的值 <c:out value=&qu ...
相关推荐
综上所述,这份"OGNL语言中文资料"应该涵盖了OGNL的基本概念、语法特性以及在实际开发中的应用案例,是学习和掌握OGNL的宝贵资源。通过深入学习和实践,开发者能够更好地利用OGNL提升代码的灵活性和可维护性。
OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,常用于Java应用程序,特别是与Struts2框架一起使用。它允许程序开发者通过简洁的语法来访问和操作对象的属性,执行复杂的逻辑,以及动态地构建...
本篇将详细介绍OGNL的使用方法及其核心概念。 一、OGNL的基础知识 1. **表达式语法**:OGNL表达式通常由对象名、点号和属性名组成,例如`user.name`,表示获取`user`对象的`name`属性。也可以通过索引访问集合元素...
在Struts2框架中,OGNL是默认的表示层语言,用于视图与模型之间的数据绑定。它使得视图可以直接引用模型中的数据,简化了MVC架构中的数据传递。例如,`<s:textfield name="user.name" />`,这里的`name`属性就是一个...
五、优化与最佳实践 1. 使用`@SkipValidation`注解来避免不必要的验证,提高性能。 2. 对用户输入进行过滤和转义,防止OGNL注入。 3. 合理配置Struts2的OGNL上下文,限制可以访问的对象和方法。 4. 使用`ValueStack`...
3. **学习文档**:官方文档会详细介绍OGNL的语法和用法,是学习的基础。 4. **参与社区**:加入OGNL相关的开发者社区,讨论问题,分享经验,获取最新的信息和更新。 总而言之,ognl-2.6.11.jar的源码提供了深入了解...
5. **OGNL API**:API文档会详细介绍如何在Java代码中使用OGNL,包括解析和评估表达式,设置和获取值,以及与其他Java对象交互的方法。 6. **安全考虑**:由于OGNL的强大功能,如果不正确地使用,可能会导致安全...
**OGNL(Object-Graph Navigation Language)**是一种强大的表达式语言,主要用于获取和设置Java对象的属性。在Java开发中,尤其是Web应用框架如Struts2和Hibernate中,OGNL被广泛使用。它允许开发者以简洁的方式...
**OGNL(Object-Graph Navigation Language)**是一种强大的表达式语言,主要被广泛应用于Java领域,用于获取和设置对象的属性。它允许开发者通过简洁的语法来导航对象图,执行复杂的逻辑运算,以及调用方法。这篇...
**OGNL(Object-Graph Navigation Language)** 是一个强大的表达式语言,用于获取和设置Java对象的属性。它被广泛应用于各种Java框架中,如Struts2,它允许开发者通过简洁的语法来操作对象和它们的属性。在这个场景...
OGNL支持自动类型转换,这意味着你可以直接在表达式中混合不同类型的值,如字符串与数字的相加。此外,还可以通过注册自定义类型转换器来扩展这种能力。 5. 集合操作: OGNL提供了一组内置的操作符,用于处理集合...
在这个“Struts2 OGNL用法项目”中,我们将深入探讨OGNL(Object-Graph Navigation Language),它是Struts2中一个强大的表达式语言,用于在模型对象和视图之间进行数据绑定和表达式计算。 OGNL是Struts2的核心组件...
**学习与实践** 要熟练掌握OGNL,你需要通过实际项目练习,了解其在不同场景下的应用。同时,阅读官方文档,理解其语法和特性,遇到问题时,查阅相关资料或社区解答,不断积累经验。 总结,OGNL是Java Web开发中的...
同时,结合实际项目实践,将理论知识与实际操作相结合,有助于更深入地理解和运用OGNL。 总之,OGNL作为一款强大的表达式语言,对于Java开发者尤其是Web开发者来说,掌握其使用和原理能够极大地提升开发效率。通过...
10. **应用实践**:结合实际项目,尝试使用OGNL解决数据绑定、动态计算等问题,进一步巩固理论知识。 通过对OGNL源码的学习,你可以更深入地理解Java中的反射、动态代理等技术,并能够更好地利用OGNL解决实际问题,...
OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,用于获取和设置Java对象的属性。在Java世界中,它广泛应用于各种框架,如Struts2、Spring等,用于动态数据绑定和表达式计算。本资料将深入探讨...
描述中提到的"ognl标签"是指Struts2提供的与OGNL相关的标签库,它们使得在JSP页面上更加方便地使用OGNL表达式。例如,`<s:property>`标签可以用来输出对象的属性值,其value属性可以是OGNL表达式,如`...
OGNL (Object-Graph Navigation Language) 是一种强大的表达式语言,用于获取和设置Java对象的属性。它在Java开发中广泛应用于MVC框架,如Struts2,因为它能方便地处理视图和模型之间的数据绑定。这篇文档将深入探讨...
OGNL是Java语言中的一个表达式语言,用于动态获取和设置对象属性。它的名称来源于其能力:遍历和操作对象图。在Web应用中,特别是Struts2框架,OGNL被广泛用于视图层和模型层之间的数据绑定。它支持丰富的表达式,...
6. **示例与最佳实践**:提供丰富的示例代码和最佳实践,帮助开发者更好地理解和使用OGNL。 通过阅读《OGNL Language Guide》的中文版,开发者可以更深入地理解OGNL的工作原理,从而更有效地利用它来提升Struts应用...