ONGL介绍

1.简介

OGNL:Object Graph Navigation Language,是一种功能强大的表达式语言,可以存取对象的属性,调用对象的方法等。

著名的Struts2使用它来实现UI和Action之间的数据绑定。

2.两个重要的API

Ognl.getValue(String expression, Object root);

从root对象中获取expression对应的值

Ognl.getValue(String expression, Map<String, Object> context, Object root);

从根对象为root的上下文context中获取expression对应的值

我们可以从下面一段代码中看出context和root的区别

User user =  new User();
user.setId("001");
Map<String, String> ognlCtxt = new HashMap<String, String>();
ognlCtxt.put("id", "007");
assertEquals("001", Ognl.getValue("id", ognlCtxt, user));
assertEquals("001", Ognl.getValue("#root.id", ognlCtxt, user));

assertEquals("007", Ognl.getValue("#id", ognlCtxt, user));
assertEquals("007", Ognl.getValue("#context.id", ognlCtxt, user));

当expression以#开头时,将从context中取值

当expression直接以property名字开头时,将从root中取值

并且context中有两个属性#root指向root对象,#context指向本身

具体原因请参考OGNL源代码

3.主要使用

1)常量

--String:用'或"包围

--char:用'包围

--数字:数字格式,或者添加后缀b(B,表示BigDecimals),后缀h(H,表示BigIntegers)

--Boolean:保留字true/false

--null:保留字null

  

// String
assertEquals("id", Ognl.getValue("\"id\"", null));
assertEquals("id", Ognl.getValue("'id'", null));
// char
assertEquals('i', Ognl.getValue("'i'", null));	
// Number
assertEquals(22, Ognl.getValue("22", null));	
// boolean
assertTrue((Boolean) Ognl.getValue("true", null));
// null
assertNull(Ognl.getValue("null", null));

  

 2)new新建对象

--java.lang包中的类对象:new

  

   new String()

--其它包中的类对象:new,但要使用类全名

  new java.util.ArrayList()

--List:用大括号包围,元素之间用","分隔

   {"badminton",  "CS"}

--数组:和Java类似

  

   new int[]{1, 2, 3}

   new int[5]

--Map:以#开头,用大括号包围,类似于Json格式,Key和Value之间用":"分隔,Entry之间使用"," 分隔

          可以同构在#之后用"@"包围的类全名来指定

   #{"name" : "007", "age" : 45}

   #@java.util.LinkedHashMap@{"name" : "007", "age" : 45}

// object in java.lang.*
assertTrue(Ognl.getValue("new String()", null) instanceof String);
// object not in java.lang.*
assertTrue(Ognl.getValue("new java.util.ArrayList()", null) instanceof List);

/* Collection */
// List
assertTrue(Ognl.getValue("{0, 1, 2}", null) instanceof List);
// Array
assertTrue(Ognl.getValue("new int[]{0, 1, 2}", null) instanceof int[]);
assertTrue(Ognl.getValue("new int[5]", null) instanceof int[]);
// Map
assertTrue(Ognl.getValue("#{'name' : 'man', 'age' : 25}", null) instanceof Map);
assertTrue(Ognl.getValue("#@java.util.HashMap@{'name' : 'man', 'age' : 25}", null) instanceof HashMap);

3)获取对象属性

通过.或者[]访问,以下内容均可视为对象的属性

--JaveBean中的属性

--List或者Array对象的index

--Map对象的key

--[]还支持对一下成对出现方法的index的直接访问(必须成对出现)

public PropertyType getPropertyName(int index);

public void setPropertyName(int index, PropertyType value);

public PropertyType getPropertyName(IndexType index);

public void setPropertyName(IndexType index, PropertyType value);

--除此之外为了OGNL还为Collection对象提供了一些伪属性

Collection : size/isEmpty

List : iterator

Map : keys, values(注:假如Map中有一key的名字为size,则必须通过[]方式获取,.方式将返回Map的大小值)

Set : iterator

Iterator : next/hasNext

Enumeration : next/hasNext/nextElement/hasMoreElements

--.和[]的区别:[]支持表达式

User user = new User();
user.setId("001");
user.setName("man1");
user.setAge(22);
List<String> hobbies = new ArrayList<String>();
hobbies.add("badminton");
hobbies.add("name");
user.setHobbies(hobbies);
Map<String, List<String>> relations = new HashMap<String, List<String>>();
List<String> friends = new ArrayList<String>();
friends.add("002");
relations.put("friends", friends);
user.setRelations(relations);

//property 
assertEquals("001", Ognl.getValue("id", user));

/*index*/
// List
assertEquals("badminton", Ognl.getValue("hobbies[0]", user));
// Map
assertEquals("002", Ognl.getValue("relations['friends'][0]", user));
// getHobby(...)/setHobby(...)
assertEquals("badminton", Ognl.getValue("hobby[0]", user));
// getRelation(...)/setRelation(...)
assertEquals("002", Ognl.getValue("relation['friends'][0]", user));

//difference between . and []
assertEquals("man1", Ognl.getValue("[hobbies[1]]", user));

// pseudo property
assertEquals(2, Ognl.getValue("hobbies.size", user));

4)调用方法

直接通过.method(param1, ..., paramN)的方式访问

注意:当方法重载,并且参数符合多个方法要求时,OGNL会选择任意一个进行执行。

所以当方法存在重载,并且参数中有null值时需特别注意,因为null符合任何参数类型要求

assertEquals(2, Ognl.getValue("{0, 1}.size()", null));

  

5)Static属性和方法

--static属性@class@field

--static方法@class@method(param1, ..., paramN)

// static method
assertEquals("User", Ognl.getValue("@com.siyuan.ognltest.entity.User@getEntityName()", null));
// static field
assertEquals("User", Ognl.getValue("@com.siyuan.ognltest.entity.User@ENTITY_NAME", null));

6)变量

以#开头的属性名均作为context中的变量,并且可通过=对其进行赋值,假如不存在,则新建并保存在context中

#this为一特殊变量,指示前一段表达式的值

assertEquals(120, Ognl.getValue("#count = 100, #count + 20", null));
assertEquals(120, Ognl.getValue("(#count=100).(#this>100 ? 2*#this : 20+#this)", null));

OgnlContext ognlCtxt = new OgnlContext();
assertEquals(120, Ognl.getValue("#count = 100, #count + 20", ognlCtxt, ""));
assertEquals(100, Ognl.getValue("count", ognlCtxt));

  

7)运算符

除了Java中的运算符,OGNL添加了下列特殊的运算符

--in/not in

返回boolean值,表示元素是否存在list或array中

--projection

collection.{ognlExpression}

返回一个新的集合,集合的元素为遍历collection,并使用ognlExpression求值后的值

--match

collection.{? ognlBooleanExpression}

返回一个新的集合,集合的元素为遍历collection,并使用ognlExpression求值后为true的元素

--first match

collection.{^ ognlBooleanExpression}

返回一个新的集合,集合的元素为遍历collection,并使用ognlExpression求值后第一个为true的元素

--last match

collection.{$ ognlBooleanExpression}

返回一个新的集合,集合的元素为遍历collection,并使用ognlExpression求值后最后一个为true的元素

// in & not in
assertTrue((Boolean) Ognl.getValue("'badminton' in {'badminton', 'CS'}", null));
assertTrue((Boolean) Ognl.getValue("4 not in new int[]{1, 2, 3}", null));

User user = new User();
user.setId("000");
User user1 = new User();
user1.setId("001");
User user2 = new User();
user2.setId("002");
List<User> users = new ArrayList<User>();
users.add(user);
users.add(user1);
users.add(user2);
// projection
List<String> ids = (List<String>) Ognl.getValue("#root.{id}", users);
assertEquals("000", ids.get(0));
assertEquals("001", ids.get(1));
assertEquals("002", ids.get(2));
// selection
List<User> filteredUsers = (List<User>) Ognl.getValue("#root.{? #this.id instanceof String}", users);
assertEquals(user, Ognl.getValue("#root[0]", filteredUsers));
// first match
List<User> filteredUsers1 = (List<User>) Ognl.getValue("#root.{^ #this.id instanceof String}", users);
assertEquals(user, Ognl.getValue("#root[0]", filteredUsers1));
List<User> filteredUsers2 = (List<User>) Ognl.getValue("#root.{$ #this.id instanceof String}", users);
assertEquals(user2, Ognl.getValue("#root[0]", filteredUsers2));

4.参考资料

http://commons.apache.org/ognl/

猜你喜欢

转载自orange5458.iteye.com/blog/1681888