OGNL使用詳解一:原理與常用語法方式
OGNL:Object-Graph Navigation Language,一種功能強大的表達式語言(Expression Language,簡稱爲EL),通過它簡單一致的表達式語法,可以存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現字段類型轉化等功能。它使用相同的表達式去存取對象的屬性。
以上關於OGNL的定義是在百度百科中的描述,其實通俗的講,就是ognl的context對象解析一個ognl字符串,返回相應的結果。
簡單講一下OGNL的幾個重要的概念:
1.OgnlContext:它實現了Map接口,以key-value鍵值對形式存在,不同於普通map的是,裏面存在唯一的叫做根的對象(root),可以通過程序設定上下文中哪個對象是根對象。
2.root對象:root對象與普通對象都是OgnlContext中的元素,但是OgnlContext默認取根對象,如果是非根對象,需要在ognl表達式前加"#"。
3.OgnlContext裏面默認就放了四個對象:request,application,session,parameters。
4.OgnlContext的根對象在初始化時是空的
這裏需要提一句,OGNL本身和Struts2沒有任何關係,經常聽到有人說OGNL是Struts2的,對此很無語。僅僅是Struts2支持OGNL,並且在此基礎上增加了一些東西。
由於語法過於複雜,以下用一個demo項目來做演示:
第一步:新建一個Java Project
第二步:引入兩個ognl需要的jar:ognl.3.0.6.jar,javassist-3.11.0.jar包。
第三步:加入兩個bean:
package ognl.bean;
/**
*
* @author wangjian
*
*/
public class Dog {
private String name;
private String[] friends;
public String[] getFriends() {
return friends;
}
public void setFriends(String[] friends) {
this.friends = friends;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package ognl.bean;
/**
*
* @author wangjian
*
*/
public class Person {
private String name;
private Dog dog;
public Person() {
super();
}
public Person(String name) {
this.name = name;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
System.out.println("getName invoked!");
return name;
}
public void setName(String name) {
this.name = name;
}
}
第四步:編寫OGNL語法測試類:
package ognl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import ognl.bean.Dog;
import ognl.bean.Person;
/**
*
* @author wangjian
*
*/
public class OGNLTest {
public static void main(String[] args) throws OgnlException {
Person person = new Person();
person.setName("Steven");
Dog dog2 = new Dog();
dog2.setName("hello world");
person.setDog(dog2);
Dog dog = new Dog();
dog.setName("hello world your sister");
OgnlContext context = new OgnlContext();
// 把對象以鍵值對形式放進去
context.put("person", person);
context.put("dog", dog);
// 設定這個OGNL的根root是person對象
context.setRoot(person);
// 解析一個表達式(取跟對象的屬性的時候,無需加#,直接寫屬性名字,默認從根對象中取屬性)
Object object = Ognl.parseExpression("name");
System.out.println(object);
Object object2 = Ognl.getValue(object, context, context.getRoot());
System.out.println(object2);
System.out.println("----------------------------");
// #表示取的不是根對象,表示取context裏面存的person對象裏面的name屬性
Object object3 = Ognl.parseExpression("#person.name");
System.out.println(object3);
Object object4 = Ognl.getValue(object3, context, context.getRoot());
System.out.println(object4);
System.out.println("----------------------------");
// #表示取的不是根對象,表示取context裏面存的dog對象裏面的name屬性
Object object5 = Ognl.parseExpression("#dog.name");
System.out.println(object5);
Object object6 = Ognl.getValue(object5, context, context.getRoot());
System.out.println(object6);
System.out.println("----------------------------");
// 屬性後買年可以直接調String的方法
Object object7 = Ognl.parseExpression("name.toUpperCase().length()");
System.out.println(object7);
Object object8 = Ognl.getValue(object7, context, context.getRoot());
System.out.println(object8);
System.out.println("----------------------------");
// 調用ONGL的靜態方法時用兩個@@符號:@表示類名@表示方法名
Object object9 = Ognl.parseExpression("@java.lang.Integer@toBinaryString(10)");
System.out.println(object9);
Object object10 = Ognl.getValue(object9, context, context.getRoot());
System.out.println(object10);
System.out.println("----------------------------");
// 調用ONGL的靜態方法時用兩個@@符號:不寫類名,默認是java.lang.Math類,@@直接寫Math類裏面的方法
Object object11 = Ognl.parseExpression("@@min(4, 10)");
System.out.println(object11);
Object object12 = Ognl.getValue(object11, context, context.getRoot());
System.out.println(object12);
System.out.println("----------------------------");
// new一個LinkedList
Object object13 = Ognl.parseExpression("new java.util.LinkedList()");
System.out.println(object13);
Object object14 = Ognl.getValue(object13, context, context.getRoot());
System.out.println(object14);
System.out.println("----------------------------");
// 一個字符串集合(外面用雙引號了,裏面就用單引號),
Object object15 = Ognl.getValue("{'aa', 'bb', 'cc', 'dd'}", context,context.getRoot());
System.out.println(object15);
System.out.println("----------------------------");
// 一個字符串集合(OGNL中,集合與數組是等同的),取第三個元素
Object object16 = Ognl.getValue("{'aa', 'bb', 'cc', 'dd'}[2]", context,context.getRoot());
System.out.println(object15);
System.out.println("----------------------------");
dog.setFriends(new String[] { "aa", "bb", "cc" });
// dog對象的friends數組
Object object17 = Ognl.getValue("#dog.friends", context,context.getRoot());
System.out.println(object17);
System.out.println("----------------------------");
dog.setFriends(new String[] { "aa", "bb", "cc" });
// dog對象的friends數組的第二個元素
Object object18 = Ognl.getValue("#dog.friends[1]", context,context.getRoot());
System.out.println(object18);
List<String> list = new ArrayList<String>(Arrays.asList("hello","world", "hello world"));
context.put("list", list);
System.out.println(Ognl.getValue("#list", context, context.getRoot()));
System.out.println(Ognl.getValue("#list[1]", context, context.getRoot()));
System.out.println("----------------------------");
// OGNL的映射(Map):#{}表示這是一個映射Map,這裏的#與取非根元素的#不同,僅僅表示這是一個映射Map而已
System.out.println(Ognl.getValue("#{'key1': 'value1', 'key2': 'value2', 'key3': 'value3', 'key4': 'value4'}",context, context.getRoot()));
// OGNL返回映射中某key對應的value
System.out.println(Ognl.getValue("#{'key1': 'value1', 'key2': 'value2', 'key3': 'value3', 'key4': 'value4'}['key3']",context, context.getRoot()));
System.out.println("----------------------------");
List<Person> persons = new ArrayList<Person>(Arrays.asList(new Person("doctor"), new Person("worker"), new Person("student")));
context.put("persons", persons);
// 過濾:collection.{?開頭
// expression},對一個集合進行過濾,返回過濾後結果(OGNL提供了僞屬性,"#persons.{? #this.name.length() > 4}.size"也可以)
System.out.println(Ognl.getValue("#persons.{? #this.name.length() > 4}", context,context.getRoot()));
System.out.println(Ognl.getValue("#persons.{? #this.name.length() > 4}.size()", context,context.getRoot()));
System.out.println(Ognl.getValue("#persons.{? #this.name.length() > 4}[0].name", context,context.getRoot()));
// 過濾(filtering),獲取到過濾後的集合中的第一個元素^, collection.{^ expression}
System.out.println(Ognl.getValue("#persons.{^ #this.name.length() > 4}", context,context.getRoot()));
// 過濾(filtering),獲取到過濾後的集合中的第一個元素$, collection.{$ expression}
System.out.println(Ognl.getValue("#persons.{$ #this.name.length() > 4}", context,context.getRoot()));
System.out.println("----------------------------");
// 投影(projection), collection. {expression}
System.out.println(Ognl.getValue("#persons.{name}", context,context.getRoot()));
System.out.println("----------------------------");
System.out.println(Ognl.getValue("#persons.{#this.name.length() <= 5 ? 'Hello World' : #this.name}",context, context.getRoot()));
}
}