Ognl简介及基本使用
OGNL(Object Graph Navigation Language)对象导航语言。
OGNL是基于java实现,本身与Strut没有任何关系,只是Struts2的API对其进行解析。
Ognl当中有OgnlConext(Ogn上下文),该类实现了java.util.Map。
Ognl当中存在唯一的一个Root(根)的对象,root对象可以通过程序自己设定上下文中的哪个对象作为根对象。
使用OGNL需要2个jar,ognl.jar和javassist.jar.
public static void main(String[] args) throws Exception {
Person person = new Person();
person.setName("张三");
Dog dog = new Dog();
dog.setName("旺财");
OgnlContext ognlContext = new OgnlContext();//ognl上下文对象
ognlContext.put("person", person);
ognlContext.put("dog", dog);
ognlContext.setRoot(person);//将person设置为ognl的根对象
Object object1 = Ognl.parseExpression("name");
Object object2 = Ognl.getValue(object1, ognlContext,ognlContext.getRoot());
System.out.println("object1: "+object1);
System.out.println("object2: "+object2);
System.out.println("-----------------");
Object object3 = Ognl.parseExpression("#person.name");
Object object4 = Ognl.getValue(object3, ognlContext,ognlContext.getRoot());
System.out.println("object3: "+object3);
System.out.println("object4: "+object4);
System.out.println("-----------------");
Object object5 = Ognl.parseExpression("#dog.name");
Object object6 = Ognl.getValue(object5, ognlContext,ognlContext.getRoot());
System.out.println("object5: "+object5);
System.out.println("object6 "+object6);
System.out.println("----------------");
person.setDog(dog);//为person设置dog属性
Object object7 = Ognl.parseExpression("dog.name");
Object object8 = Ognl.getValue(object7, ognlContext,ognlContext.getRoot());
System.out.println("object7: "+object7);
System.out.println("object8: "+object8);
}
上面代码将person对象设置为root,那么在输入表达式时,如果不使用“#”开头,那么ognl则会从设置的root对象当中去调用属性的get方法,直接获取值,如果使用“#”开头,那么则会从“#”后面当中的对象中获取值,所以上面程序运行的结果为:
object1: name
object2: 张三
-----------------
object3: #person.name
object4: 张三
-----------------
object5: #dog.name
object6 旺财
----------------
object7: dog.name
object8: 旺财
ognl当中一样可以指定调用对象的方法,如下:
Object object9 = Ognl.parseExpression("name.substring(0, 1)");
Object object10 = Ognl.getValue(object9, ognlContext,ognlContext.getRoot());
System.out.println("object9: "+object9);
System.out.println("object10: "+object10);
上面代码运行后的结果为:
object9: name.substring(0, 1)
object10: 张
Ognl调用静态方法和静态成员变量
ognl当中调用静态方法,表达式需要用到两个“@”符号,而且@与@中间要放置该静态方法所属的类的全称(包括包名),
表达式为:@packnage.className@methodName(params)举例如下:
Object object11 = Ognl.parseExpression("@java.lang.Integer@toBinaryString(10)");
Object object12 = Ognl.getValue(object11,ognlContext, ognlContext.getRoot());
System.out.println("object11: "+object11);
System.out.println("object12: "+object12);
输出结果为:
object11: @java.lang.Integer@toBinaryString(10)
object12: 1010
对于OGNL来说,java.lang.Math是其默认类,如果调用java.lang.Math的静态方法,则不需要特别指定其类,如:
Object object13 = Ognl.parseExpression("@@min(4,10)");
Object object14 = Ognl.getValue(object13, ognlContext,ognlContext.getRoot());
System.out.println("object13: "+object13);
System.out.println("object14: "+object14);
输出结果为:
object13: @java.lang.Math@min(4, 10)
object14: 4
ognl同样可以访问类的静态成员变量:
Object object15 = Ognl.parseExpression("@@PI");
Object object16 = Ognl.getValue(object15, ognlContext,ognlContext.getRoot());
System.out.println("object13: "+object15);
System.out.println("object14: "+object16);
输出结果为:
object13: @java.lang.Math@PI
object14: 3.141592653589793
Ognl集合使用
对于ognl来说数组和集合是一样的,都是通过下标索引去访问。构造集合的时候使用{...}形式:
Object object17 = Ognl.getValue("{'aa','bb','cc','dd'}", ognlContext,ognlContext.getRoot());
System.out.println("object17: "+object17);
Object object18 = Ognl.getValue("{'aa','bb','cc','dd'}[2]", ognlContext,ognlContext.getRoot());
System.out.println("object18: "+object18);
object17: [aa, bb, cc, dd]
object18: cc
List<String> friends = new ArrayList<String>();
friends.add("aa");
friends.add("bb");
friends.add("cc");
dog.setFriends(friends);
Object object19 = Ognl.getValue("#dog.friends[1]", ognlContext,ognlContext.getRoot());
System.out.println("object19: "+object19);
object19: bb
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("hello world");
ognlContext.put("list", list);
Object object20 = Ognl.getValue("#list[0]", ognlContext,ognlContext.getRoot());
System.out.println("object20: "+object20);
object20: hello
Ogl处理映射(Map)
使用ognl处理映射(Map)时得语法格式如下
#{‘key1’:'value1','key2':'value2','key3':'value3'}
Map<String, String> map = new HashMap<String, String>();
map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
map.put("key4","value4");
ognlContext.put("map", map);
Object object21 = Ognl.getValue("#map['key3']", ognlContext,ognlContext.getRoot());
System.out.println(object21);
过滤(filtering):collection.{? expression}
List<Person> persons = new ArrayList<Person>();
Person p1 = new Person();
Person p2 = new Person();
Person p3 = new Person();
p1.setName("zhangsan");
p2.setName("lisi");
p3.setName("wangwu");
persons.add(p1);
persons.add(p2);
persons.add(p3);
ognlContext.put("persons", persons);
//#this表示当前集合的对象,相当于java中的增强for循环
//object22是集合
Object object22 = Ognl.getValue("#persons.{? #this.name.length() > 4}", ognlContext,ognlContext.getRoot());
Object object23 = Ognl.getValue("#persons.{? #this.name.length() > 4}.size", ognlContext,ognlContext.getRoot());
Object object24 = Ognl.getValue("#persons.{? #this.name.length() > 4}.size()", ognlContext,ognlContext.getRoot());
Object object25 = Ognl.getValue("#persons.{? #this.name.length() > 4}[0].name", ognlContext,ognlContext.getRoot());
System.out.println("object22: "+object22);
System.out.println("object23: "+object23);
System.out.println("object24: "+object24);
System.out.println("object25: "+object25);
object22: [com.iron.ognl.Person@122cdb6, com.iron.ognl.Person@1ef9157]
object23: 2
object24: 2
object25: zhangsan
OGNL针对集合提供了一些伪属性(如size,isEmpty),让我们可以通过属性的方式来调用方法(本质原因在于集合当中的很多方法并不符合JavaBean的命名规则),但我们依然可以通过调用方法来实现与伪属性相同的目的。
//获取集合中的第一个元素,collection.{^ expression},返回的仍然是集合,只不过只有一个元素
Object object26 = Ognl.getValue("#persons.{^ #this.name.length() > 4}", ognlContext,ognlContext.getRoot());
Object object27 = Ognl.getValue("#persons.{^ #this.name.length() > 4}[0].name", ognlContext,ognlContext.getRoot());
System.out.println(object26);
System.out.println(object27);
[com.iron.ognl.Person@122cdb6]
zhangsan
//获取集合中的最后一个元素,collection.{$ expression},返回的仍然是集合,只不过只有一个元素
Object object28 = Ognl.getValue("#persons.{$ #this.name.length() > 4}", ognlContext,ognlContext.getRoot());
投影(projection):collection.{expression}
过滤和投影的区别是:类比于表的查询操作,过滤是取行操作,投影则是取列操作。
System.out.println(Ognl.getValue("#persons.{name}", ognlContext,ognlContext.getRoot()));
System.out.println(Ognl.getValue("#persons.{name.length() > 5 ? name : 'hello'}", ognlContext,ognlContext.getRoot()));
[zhangsan, lisi, wangwu]
[zhangsan, hello, wangwu]