读书人

Struts2复习(5)-OGNL的使用

发布时间: 2012-08-30 09:55:54 作者: rapoo

Struts2温习(5)--OGNL的使用

要谈OGNL在Struts2中的应用,首先得明白OGNL到底是什么


OGNL 的历史

OGNL 最初是为了能够使用对象的属性名来建立 UI 组件 (component) 和 控制器 (controllers) 之间的联系,简单来说就是:视图 与 控制器 之间数据的联系。后来为了应付更加复杂的数据关系,Drew Davidson 发明了一个被他称为 KVCL(Key-Value Coding Language) 的语言。 Luke 参与进来后,用 ANTLR 来实现了该语言,并给它取了这个新名字,他后来又使用 JavaCC 重新实现了该语言。目前 OGNL 由 Drew 来负责维护。目前很多项目中都用到了 OGNL,其中不乏为大家所熟知的,例如几个流行的 web 应用框架:WebWork【当然struts2也可以说是WebWork升级版】,Tapestry 等。


什么是 OGNL?

OGNL 是 Object-Graph Navigation Language 的缩写,从语言角度来说:它是一个功能强大的表达式语言,用来获取和设置 java 对象的属性 , 它旨在提供一个更高抽象度语法来对 java 对象图进行导航,OGNL 在许多的地方都有应用,例如:?

1)作为 GUI 元素(textfield,combobox, 等)到模型对象的绑定语言。?

2)数据库表到 Swing 的 TableModel 的数据源语言。?

3)web 组件和后台 Model 对象的绑定语言 (WebOGNL,Tapestry,WebWork,WebObjects) 。?

4)作为 Jakarata Commons BeanUtils 或者 JSTL 的表达式语言的一个更具表达力的替代语言。?


另外,java 中很多可以做的事情,也可以使用 OGNL 来完成,例如:列表映射和选择。对于开发者来说,使用 OGNL,可以用简洁的语法来完成对 java 对象的导航。通常来说:通过一个“路径”来完成对象信息的导航,这个“路径”可以是到 java bean 的某个属性,或者集合中的某个索引的对象,等等,而不是直接使用 get 或者 set 方法来完成




OGNL 的基本语法

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 表达式

1)常量:字符串:“ hello ” 字符:‘ h ’ 数字:除了像 java 的内置类型 int,long,float 和 double,Ognl 还有如例:

0.01B,相当于 java.math.BigDecimal,使用’ b ’或者’ B ’后缀。 100000H,相当于 java.math.BigInteger,使用’ h ’ 或 ’ H ’ 后缀。

2)属性的引用例如:user.name

3)变量的引用例如:#name

4)静态变量的访问使用 @class@field

5)静态方法的调用使用 @class@method(args), 如果没有指定 class 那么默认就使用 java.lang.Math.

6)构造函数的调用例如:new java.util.ArrayList();

其它的 Ognl 的表达式可以参考 Ognl 的语言手册。?



OGNL的性能


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);?

实践证明:OGNL 非常接近 java 直接调用的时间。



?

表达式语言主要有以下几大好处:

1)避免(MyType) request.getAttribute()和myBean.getMyProperty()之类的语句,使页面更简洁;?

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

3)简单明了地表达代码逻辑,使用代码更可读与便于维护。?


Struts 2中的表达式语言

Struts 2支持以下几种表达式语言:

1)OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言;?

2)JSTL(JSP Standard Tag Library),JSP 2.0集成的标准的表达式语言;?

3)Groovy,基于Java平台的动态语言,它具有时下比较流行的动态语言(如Python、Ruby和Smarttalk等)的一些起特性;?

4)Velocity,严格来说不是表达式语言,它是一种基于Java的模板匹配引擎,具说其性能要比JSP好。?


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

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

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

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

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

操作集合对象。?





Struts2中ONGL的使用示例

index.html



?User.java



?OGNLAction.java


?

总结:

在上边大家都好奇为什么都用struts的S标签,因为OGNL是通常要结合Struts 2的标志一起使用,如<s:property value="xx" />


?Action类与JSP页面之间的数据传递

?1) 通过HttpServletRequest,HttpSession,ServletContext来传递数据。

?? ?a) Action中传数据:在Action类的请求处理方法中先获取各个作用域对象

?? ?ServletActionContext.getRequest();

?? ?ServletActionContext.getRequest().getSession();

?? ?ServletActionContext.getServletContext();

?? ? ? ? ?然后调用相应的setAttribute(String "键", Object 值);

?? ?b) 在JSP页面中取数据:可以使用EL表达式或代码片段来取出对应作用域中属性值。

?? ?c) 页面中的请求参数传递到Action中时,Action中直接定义对应名称的属性,并提供setter方法即可封装此数据。

?? ?

?2) 通过ActionContext实例来传递数据。 ActionContext针对每个正在执行Action的线程中绑定一份。

?? a) Action中通过ActionContext传递数据。

?? ? ?ActionContext提供了put(String "键", Object 值); ?//数据不会映射到HttpServletRequest中。

?? ? ?ActionContext提供的getSession().put(String "键", Object 值); ?//数据会自动映射到HttpSession中。

?? ? ?ActionContext提供的getApplication().put(String "键", Object 值); //数据会自动映射到ServletContext中。

?? b) 在JSP页面取数据:struts2推荐使用OGNL来取ActionContext中的数据。



1. Struts2中的OGNL的使用。


2. OGNL:对象图导航语言。通过OGNL表达式可以获取对象的属性,调用对象的方法,或构造出对象。

??1) OGNL上下文中有一个根对象。这个根对象可以直接获取。不需要#。

??2)支持常量:

?? ? ? ? 字符串常量、字符常量、

?? ? ? ? 数值常量:int、long、float、double

?? ? ? ? 布尔常量:true、false

?? ?Null常量 : null

?? ? ? ? 支持操作符:支持Java的所有操作符,还支持特有的操作符: ,、 {}、in、not in;


?Struts2中的OGNL:

??1) Struts2将ActionContext设置为OGNL上下文,并将值栈(ValueStack)作为OGNL的根对象放置到ActionContext中。

??2) Struts2总是把当前Action实例放置在值栈的栈顶。所以,在OGNL中引用Action中的属性也可以省略“#”。

??

?常用标签

?1) <s:property value="OGNL"/>

?2) <s:date name="OGNL" format=""/>

?3) <s:if test="OGNL"></s:if><s:elseif test="OGNL"></s:elseif><s:else></s:else>

★4) <s:iterator value="OGNL" status="vs">...</s:iterator>

?5) <s:debug/>

?


struts2中#、%和$这三个符号的使用方法【摘自max struts2教程】?

?

一、"#"的用法?

?? 1、 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:?

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

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

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

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


二、"%"的用法?

?? ?“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:?

?? ?<h3>%的用途</h3>?

?? ?<p><s:url value="#foobar['foo1']" /></p>?

?? ?<p><s:url value="%{#foobar['foo1']}" /></p>?


三、"$"的用法?

?? ?1、用于在国际化资源文件中,引用OGNL表达式?

?? ?2、在Struts 2配置文件中,引用OGNL表达式?

?? ? 例如:?

?? ? ? ? <action name="AddPhoto" /> ? ? ? ? ? ?

?? ? ? ? ? ?<result type="redirect">ListPhotos.action? ? ? ? albumId=${albumId}</result>?

?? ? ? ?</action>


读书人网 >软件架构设计

热点推荐