ognl-training (30 minutes)

30
All Rights Reserved © Alcatel-Lucent 2007, ##### OGNL-training (30 minutes) Xiang yingbing 2011-05-15

Upload: alden

Post on 12-Jan-2016

46 views

Category:

Documents


0 download

DESCRIPTION

OGNL-training (30 minutes). Xiang yingbing 2011-05-15. Content List. 1. Express Language (EL) 在 J2EE(MVC) 中的应用 2. OGNL 2.1 History 2.2 Syntax 2.3 Expressions 3. OGNL 与 ANTLR /JavaCC ( Java Compiler Compiler ) 3.1 OGNL 源代码是怎么生成出来的 3.2 AMS 和 ANTLR/JSMIPARSER 4. OGNL examples - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 2007, #####

OGNL-training(30 minutes)

Xiang yingbing

2011-05-15

Page 2: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 20072

Content List

1. Express Language (EL) 在 J2EE(MVC) 中的应用

2. OGNL2.1 History

2.2 Syntax

2.3 Expressions

3. OGNL 与 ANTLR /JavaCC ( Java Compiler Compiler )3.1 OGNL 源代码是怎么生成出来的3.2 AMS 和 ANTLR/JSMIPARSER

4. OGNL examples4.1 ArrayCreationTest

4.2 ognl\src\test\java\org\ognl\test

4.3 ArithmeticAndLogicalOperatorsTest.java

Page 3: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 20073

1. Express Language (EL) 在J2EE(MVC)中的应用(a)model

Page 4: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 20074

(b)controller

Page 5: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 20075

(c)view

Page 6: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 20076

说明:view 中, #{menuMBean.getMenu(topicQueryMBean.mid).getName()} 就是

个 EL 表达式。Controller 中, @ManagedBean(name=“menuMBean”) 中“ menuMBean” 是个

简单的 EL 表达式。

OGNL 最开始作为 MVC 架构中 UI组件和 Controllers之间的一种关联方法,利用属性名字进行关联。

JSF/JSP 页面如何显示给用户 (web browser)Web browser 发送 request(list.xhtml) 到 web containerWeb container 读取 list.xhtml文件,把所有的#{…}用适当的内容替换掉。 这个替换的过程就是对 EL表达式的解析过程。 替换完毕后, Web container 把得到的 html 页面发送回 web browser 。

不同的 web container/WEB FRAMEWORK 采用不同的 EL实现。

Struts 采用 OGNL 。JSF: sun EL ( jsf-impl.jar\com\sun\faces\el )JBossEL: http://anonsvn.jboss.org/repos/jboss-el

Page 7: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 20077

Page 8: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 20078

2. OGNLOGNL 是 Object-Graph Navigation Language 的意思;它是一个表达式语言,用于获

取 Java对象的属性,或者为之设置属性。使用相同的表达式来读取属性或者设置属性。

主页OGNL 旧的主页 : http://www.ognl.org/ [ 现在已经不可访问 ]OGNL 新的主页 : http://www.opensymphony.com/ognl/OGNL 由 OpenSymphony开发,该公司其它产品

• WebWork

• Quartz

• OSCache

• OSWorkflow

• SiteMesh

• Compass

• OGNL

• Tonic

• XWork

• OSUser

• PropertySet

• Clickstream

• OSCore

Page 9: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 20079

文档Language Guide (PDF)

下载cvs sourcecode: http://svn.opensymphony.com/svn/ognl/官方 maven 下载: http://maven.opensymphony.com/opensymphony/jars/ ognl-2.6.10-javadoc.jar 15-Feb-2007 10:53 321K ognl-2.6.10-sources.jar 15-Feb-2007 10:53 198K ognl-2.6.10.jar 15-Feb-2007 10:53 164K ognl-2.6.11-javadoc.jar 18-Feb-2007 07:47 321K ognl-2.6.11-sources.jar 18-Feb-2007 07:47 198K ognl-2.6.11.jar 18-Feb-2007 07:47 164K

应用( http://en.wikipedia.org/wiki/OGNL)• WebWork and its successor Struts2• Tapestry• Spring Web Flow• Apache Click• NReco (.NET integration framework for lightweight MDD)• op4j (op4j-ognl extension) - Java fluent interface implementation.• MyBatis - SQL mapper framework• The Thymeleaf Template Engine - A Java XML/XHTML/HTML5 template engine• Unitils - Modular Testing framework for Java

Page 10: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200710

2.1 History

OGNL 最开始作为 MVC 架构中 UI组件和 Controllers之间的一种关联方法,利用属性名字进行关联。随着对更复杂关联的需求的日益增加, Drew Davidson 创建了一个他称为 KVCL 的东西,用于 Key-Value Coding Language ,这是 Luke Blanshard 鼓动的。 Luke然后用 ANTLR重新实现了该语言,取了个新名字,这次由 Drew 鼓动的,这就是现在这种状态。后来 Luke 又用 JavaCC重新实现了该语言。所有代码的进一步维护都由 Drew 完成 (Luke 进行 spiritual 指导 ) 。

Page 11: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200711

2.2 Syntax

简单的 OGNL 表达式非常简单。该语言带有各种 features ,变得非常丰富,但是,通常情况下,你不需要关心该语言的复杂部分: the simple cases have remained that way 。比如说,要访问一个对象的 name 属性, OGNL 表达式就是 name 。要得到通过 headline 属性返回的对象的 text 属性, OGNL 表达式 就是 headline.text 。

OGNL 表达式的基本单元是导航链 (navigation chain) ,通常就叫做链“ chain” 。最简单的 chains 包含下面几部分:

Page 12: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200712

举例: name.toCharArray()[0].numericValue.toString()This expression follows these steps to evaluate:

•extracts the name property of the initial, or root, object (which the user provides to OGNL through the OGNL context)

•calls the toCharArray() method on the resulting String

•extracts the first character (the one at index 0) from the resulting array

•gets the numericValue property from that character (the character is represented as a Character object, and the Character class has a method called getNumericValue()).

•calls toString() on the resulting Integer object. The final result of this expression is the String returned by the last toString() call.

Page 13: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200713

2.3 Expressions

EL 表达式遵守的格式(语法)下面先列举一些简单的例子,以及一些重要的例子。完整内容请参见 Language Guide (PDF) 的第四章

简单的例子:array.length: 获取数组的长度array[0]: 读取数组的第一个元素array.length = array["length"] = array["len" + "gth"] session.attribute[“foo”] :从 map 中获取某 key 对应的值

Page 14: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200714

2.3.1 Variable References: #this

OGNL 在表达式的每个点号 (.) 那里存储该点号 (.) 之前的 EL 表达式的值,该值通过 #this 来获取。比如:listeners.size().(#this > 100? 2*#this : 20+#this)

第二个点 (.) 那里,存储的值为 "listeners.size()" ,接着,在括号 (...) 内部,用#this 来指向这个值,也就是 "listeners.size()" 。整个表达式的结果:如果 listeners.size() 大于 100 ,那么为 2*(listeners.size()) ;否则,整个 EL 表达式的值为 20+(listeners.size())

Page 15: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200715

2.3.2 Chained Subexpressions

如果 OGNL 表达式中,某个点号 (.) 后面跟了个括号表达式 (...) ,比如:headline.parent.(ensureLoaded(), name)那么,这个点号 (.) 之前的所有表达式 ( 这里为 headline.parent) 的值被传入括号表达式内,作为该括号表达式的 root object 。上例 (ensureLoaded(), name) 等价于:(a) rootObj1=headline.parent(b) 调用 rootObj1.ensureLoaded() 方法

【方法调用,可以用来做一些动作!比如赋值,检测,日志 ... 】(c) 然后把 rootObj1.name 作为整个表达式的值。

还可以按照这种模式,做很长的链接:obj1.obj2.(methodOfObj2(), propertyOfObj2).p1.p2.obj3.(methodOfObj3(), propertyOfObj3)

另外一个例子:obj1.(obj2).(obj3).(obj4).(obj5)  等价于: obj1.obj2.obj3.obj4.obj5

Page 16: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200716

其余内容,自己研究。

Page 17: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200717

Page 18: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200718

3. OGNL 与 ANTLR /JavaCC(Java Compiler Compiler )前面 History 中,我们提到:

Luke 然后用 ANTLR 重新实现了该语言,取了个新名字,这次由 Drew 鼓动的,这就是现在这种状态。后来 Luke又用 JavaCC 重新实现了该语言。

JavaCC/ANTLR

Java Compiler Compiler [tm] (JavaCC [tm]) is the most popular parser generator for use with Java [tm] applications. A parser generator is a tool that reads a grammar specification and converts it to a Java program that can recognize matches to the grammar. In addition to the parser generator itself, JavaCC provides other standard capabilities related to parser generation such as tree building (via a tool called JJTree included with JavaCC), actions, debugging, etc.

JavaCC 是一种 grammar parser generator :语法解析器的生成器。也就是用于生成语法解析器。ANTLR 也是类似的工具

很多语言,比如 Java , HTML , C/C++ , OGNL , MIB ,都遵循一定的格式。那么,就可以用 ANTLR/JAVACC 为这些语言生成 parser 以解析这些语言。

Page 19: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200719

3.1 OGNL源代码是怎么生成出来的ognl-2.6.9-sources\ognl\src\java\ognl

• ArrayElementsAccessor.java

• ArrayPropertyAccessor.java

• ASTAdd.java

• …

• ognl.jjt

• ognl.jj

ognl-2.6.9-sources\ognl\build.xml

Page 20: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200720

用 JAVACC 生成 OGNL 的 Compiler(OGNL 源代码 ) 过程:• <java classname=“org.javacc.jjtree.Main”…> 根据 ognl.jjt文件生成一些 java文件和 ognl.jj文件

• <java classname=“org.javacc.parser.Main” …>根据 ognl.jj再生成一些 java文件。

• 生成的 Java文件可以用来读取并解析符合 OGNL 语言规范的 EL 表达式。也就是说,这些 JAVA文件组成OGNL compiler。比如 a+b , OGNL解析它的时候,就能理解该表达式的意思是 a 加上 b。

• 如果想要计算 EL 表达式的值,或者根据 EL 表达式为 java 对象设置值,那么需要手工加入 (OGNL 开发人员已经完成 ) 一些代码,一边 OGNL解析完 EL 表达式的时候,接着执行 get/set 。

Page 21: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200721

3.2 AMS 和 ANTLR/JSMIPARSER 【扩展内容,快速提示】AMS使用了 jsmiparser解析MIB ,而 jsmiparser 采用了 antlr 语法解析器生成器。通 OGNL一样, jsmiparser 也可以用 JAVACC 实现。

JSMIPARSER 读取 MIB文件9.0.10\basic.fttbmdu.1.2\axs-fttbmdu-mobject-plugin

(a) \src\main\resources\META-INF\mobject-mibs.xml

下面这个 bean 指示哪些 mib文件名字 (路径 ) 被读入 bean id="mibFileNames"

Page 22: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200722

(b)mobject-beans.xml 用 SmiDefaultParser.parse解析mib文件,得到的结果 : bean id="mib"

Page 23: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200723

Page 24: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200724

4. OGNL examples先把 ognl-2.6.9-sources\ognl 导入 eclipse ,然后运行 ognl-2.6.9-sources\

ognl\src\test\java\org\ognl\test 中的 test cases 。

先看看改造的:

Page 25: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200725

import ognl.ExpressionSyntaxException;…

public class ArrayCreationTest { private static Root ROOT = new Root();

private static Object[][] TESTS = { // Array creation { ROOT, "new String[] { \"one\", \"two\" }", new String[] { "one", "two" } }, { ROOT, "new String[] { 1, 2 }", new String[] { "1", "2" } },

//… };

4.1 ArrayCreationTest

Page 26: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200726

接上… public static void main(String[] args) throws Exception { String expressionString = ""; Object root; for(int i=0;i<TESTS.length;i++){ try{ root = TESTS[i][0]; expressionString = (String)TESTS[i][1]; SimpleNode expression = (SimpleNode)Ognl.parseExpression(expressionString); OgnlContext context = new OgnlContext(); //OgnlContext context = (OgnlContext)Ognl.createDefaultContext(null); Object expressionvalue = Ognl.getValue(expression, context, root);// 表达式值 Object expectedvalue = TESTS[i][2];//期望值 System.out.println(expressionString+" test-->"

+ OgnlTestCase.isEqual(expressionvalue, expectedvalue)); }catch(Exception e){ if(e.getClass() == ExpressionSyntaxException.class){ System.out.println(expressionString+" test-->This is the expected Exception"); }else{ e.printStackTrace(); } } } }}

Page 27: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200727

4.2 ognl\src\test\java\org\ognl\test

所有测试 classes 的定义结构相同,都扩展 org.ognl.test.OgnlTestCase最终都是验证:表达式是否和某个期望值相同。运行过程:(a)//Root             root= new Root();Root             root= null;//(b)    OgnlContext context = (OgnlContext)Ognl.createDefaultContext(null);(c)SimpleNode expression = (SimpleNode)Ognl.parseExpression(expressionString); (d)assertTrue(isEqual(Ognl.getValue(expression , context, root), expectedResult));  

Page 28: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200728

4.3 ArithmeticAndLogicalOperatorsTest.java

public class ArithmeticAndLogicalOperatorsTest extends OgnlTestCase{ private static Object[][] TESTS = { // Double-valued arithmetic expressions { "-1d", new Double(-1) }, { "+1d", new Double(1) }, { "--1f", new Float(1) }, { "2*2.0", new Double(4) }, { "5/2.", new Double(2.5) }, { "5+2D", new Double(7) }, { "5f-2F", new Float(3) }, { "5.+2*3", new Double(11) }, { "(5.+2)*3", new Double(21) },

// BigDecimal-valued arithmetic expressions { "-1b", new BigDecimal(-1) }, { "+1b", new BigDecimal(1) }, { "--1b", new BigDecimal(1) }, ... ... { "#y + \"1\"", "11" }, { "\"1\" + #y", "11" } };

...

Page 29: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200729

这里(a) root 为空,

(b) context 为         context = (OgnlContext)Ognl.createDefaultContext(null);        context.put("x", "1");        context.put("y", new BigDecimal(1));

(c) 表达式 TESTS [i][0] 的值,总是等于期望值 TESTS [i][1]

可以到源代码中看其它例子,设计web container/ams server的时候,这些例子非常有用。

Page 30: OGNL-training (30 minutes)

All Rights Reserved © Alcatel-Lucent 200730

The END