OGNL表达式介绍
從語言角度來說:它是一個(gè)功能強(qiáng)大的表達(dá)式語言,用來獲取和設(shè)置 java 對象的屬性 ,它旨在提供一個(gè)更高抽象度語法來對 java 對象圖進(jìn)行導(dǎo)航。另外,java 中很多可以做的事情,也可以使用 OGNL 來完成,例如:列表映射和選擇。對于開發(fā)者來說,使用 OGNL,可以用簡潔的語法來完成對 java 對象的導(dǎo)航。通常來說:通過一個(gè)“路徑”來完成對象信息的導(dǎo)航,這個(gè)“路徑”可以是到 java bean 的某個(gè)屬性,或者集合中的某個(gè)索引的對象,等等,而不是直接使用 get 或者 set 方法來完成。
首先來介紹下OGNL的三要素:
一、表達(dá)式:
表達(dá)式(Expression)是整個(gè)OGNL的核心內(nèi)容,所有的OGNL操作都是針對表達(dá)式解析后進(jìn)行的。通過表達(dá)式來告訴OGNL操作到底要干些什么。因此,表達(dá)式其實(shí)是一個(gè)帶有語法含義的字符串,整個(gè)字符串將規(guī)定操作的類型和內(nèi)容。OGNL表達(dá)式支持大量的表達(dá)式,如“鏈?zhǔn)皆L問對象”、表達(dá)式計(jì)算、甚至還支持Lambda表達(dá)式。
二、Root對象:
OGNL的Root對象可以理解為OGNL的操作對象。當(dāng)我們指定了一個(gè)表達(dá)式的時(shí)候,我們需要指定這個(gè)表達(dá)式針對的是哪個(gè)具體的對象。而這個(gè)具體的對象就是Root對象,這就意味著,如果有一個(gè)OGNL表達(dá)式,那么我們需要針對Root對象來進(jìn)行OGNL表達(dá)式的計(jì)算并且返回結(jié)果。
三、上下文環(huán)境:
有個(gè)Root對象和表達(dá)式,我們就可以使用OGNL進(jìn)行簡單的操作了,如對Root對象的賦值與取值操作。但是,實(shí)際上在OGNL的內(nèi)部,所有的操作都會(huì)在一個(gè)特定的數(shù)據(jù)環(huán)境中運(yùn)行。這個(gè)數(shù)據(jù)環(huán)境就是上下文環(huán)境(Context)。OGNL的上下文環(huán)境是一個(gè)Map結(jié)構(gòu),稱之為OgnlContext。Root對象也會(huì)被添加到上下文環(huán)境當(dāng)中去。
OGNL 的基本語法:
1. 對Root對象的訪問
OGNL使用的是一種鏈?zhǔn)降娘L(fēng)格進(jìn)行對象的訪問。具體代碼如下:
@Testpublic void testOgnl(){User user = new User("rcx", "123");Address address = new Address("110003", "沈陽市和平區(qū)");user.setAddress(address);try{System.out.println(Ognl.getValue("name", user));System.out.println(Ognl.getValue("address", user));System.out.println(Ognl.getValue("address.port", user));//輸出結(jié)果://rcx//com.rcx.ognl.Address@dda25b//110003 }catch (OgnlException e){e.printStackTrace();}} View Code2. 對上下文對象的訪問
使用OGNL的時(shí)候如果不設(shè)置上下文對象,系統(tǒng)會(huì)自動(dòng)創(chuàng)建一個(gè)上下文對象,如果傳入的參數(shù)當(dāng)中包含了上下文對象則會(huì)使用傳入的上下文對象。當(dāng)訪問上下文環(huán)境當(dāng)中的參數(shù)時(shí)候,需要在表達(dá)式前面加上'#',表示了與訪問Root對象的區(qū)別。具體代碼如下:
@Testpublic void testOgnl1(){User user = new User("rcx", "123");Address address = new Address("110003", "沈陽市和平區(qū)");user.setAddress(address);Map<String, Object> context = new HashMap<String, Object>();context.put("init", "hello");context.put("user", user);try{System.out.println(Ognl.getValue("#init", context, user));System.out.println(Ognl.getValue("#user.name", context, user));System.out.println(Ognl.getValue("name", context, user));//輸出結(jié)果://hello//rcx//rcx }catch (OgnlException e){e.printStackTrace();}} View Code這段代碼很好的區(qū)分了訪問Root對象和訪問上下文對象的區(qū)別。
3. 對靜態(tài)變量的訪問
在OGNL表達(dá)式當(dāng)中也可以訪問靜態(tài)變量或者調(diào)用靜態(tài)方法,格式如@[class]@[field/method()]。具體代碼如下:
public class Constant {public final static String ONE = "one";public static void get(){}public static String getString(){return "string";} }@Testpublic void testOgnl2(){try{Object object = Ognl.getValue("@com.rcx.ognl.Constant@ONE", null);Object object1 = Ognl.getValue("@com.rcx.ognl.Constant@get()", null);Object object2 = Ognl.getValue("@com.rcx.ognl.Constant@getString()", null);System.out.println(object);System.out.println(object1);System.out.println(object2);//one//null 當(dāng)返回值是void的時(shí)候輸出的是null//string }catch (OgnlException e){e.printStackTrace();}} View Code4. 方法的調(diào)用
如果需要調(diào)用Root對象或者上下文對象當(dāng)中的方法也可以使用.+方法的方式來調(diào)用。甚至可以傳入?yún)?shù)。代碼如下:
@Testpublic void testOgnl3(){User user = new User();Map<String, Object> context = new HashMap<String, Object>();context.put("name", "rcx");context.put("password", "password");try{System.out.println(Ognl.getValue("getName()", context, user));Ognl.getValue("setName(#name)", context, user);System.out.println(Ognl.getValue("getName()", context, user));//輸出結(jié)果//null//rcx }catch (OgnlException e){e.printStackTrace();}} View Code從代碼可以看出來,賦值的時(shí)候可以選擇上下文當(dāng)中的元素進(jìn)行給Root對象的name屬性賦值。
5. 對數(shù)組和集合的訪問
OGNL支持對數(shù)組按照數(shù)組下標(biāo)的順序進(jìn)行訪問。此方式也適用于對集合的訪問,對于Map支持使用鍵進(jìn)行訪問。代碼如下:
@Testpublic void testOgnl4(){User user = new User();Map<String, Object> context = new HashMap<String, Object>();String[] strings = {"aa", "bb"};ArrayList<String> list = new ArrayList<String>();list.add("aa");list.add("bb");Map<String, String> map = new HashMap<String, String>();map.put("key1", "value1");map.put("key2", "value2");context.put("list", list);context.put("strings", strings);context.put("map", map);try{System.out.println(Ognl.getValue("#strings[0]", context, user));System.out.println(Ognl.getValue("#list[0]", context, user));System.out.println(Ognl.getValue("#list[0 + 1]", context, user));System.out.println(Ognl.getValue("#map['key1']", context, user));System.out.println(Ognl.getValue("#map['key' + '2']", context, user));//輸出如下://aa//aa//bb//value1//value2 }catch (OgnlException e){e.printStackTrace();}} View Code從上面代碼不僅看到了訪問數(shù)組與集合的方式同時(shí)也可以看出來OGNL表達(dá)式當(dāng)中支持操作符的簡單運(yùn)算。有如下所示:
2 + 4 //整數(shù)相加(同時(shí)也支持減法、乘法、除法、取余[ % / mod]、)
"hell" + "lo" //字符串相加
i++ //遞增、遞減
i == j //判斷
var in list //是否在容器當(dāng)中
6. 投影與選擇
OGNL支持類似數(shù)據(jù)庫當(dāng)中的選擇與投影功能。
投影:選出集合當(dāng)中的相同屬性組合成一個(gè)新的集合。語法為collection.{XXX},XXX就是集合中每個(gè)元素的公共屬性。
選擇:選擇就是選擇出集合當(dāng)中符合條件的元素組合成新的集合。語法為collection.{Y XXX},其中Y是一個(gè)選擇操作符,XXX是選擇用的邏輯表達(dá)式。
選擇操作符有3種:
? :選擇滿足條件的所有元素
^:選擇滿足條件的第一個(gè)元素
$:選擇滿足條件的最后一個(gè)元素
? 示例代碼如下:
@Testpublic void testOgnl5(){Person p1 = new Person(1, "name1");Person p2 = new Person(2, "name2");Person p3 = new Person(3, "name3");Person p4 = new Person(4, "name4");Map<String, Object> context = new HashMap<String, Object>();ArrayList<Person> list = new ArrayList<Person>();list.add(p1);list.add(p2);list.add(p3);list.add(p4);context.put("list", list);try{ArrayList<Integer> list2 = (ArrayList<Integer>) Ognl.getValue("#list.{id}", context,list);ArrayList<String> list3 = (ArrayList<String>) Ognl.getValue("#list.{id + '-' + name}",context, list);ArrayList<Person> list4 = (ArrayList<Person>) Ognl.getValue("#list.{? #this.id > 2}",context, list);ArrayList<Person> list5 = (ArrayList<Person>) Ognl.getValue("#list.{^ #this.id > 2}",context, list);ArrayList<Person> list6 = (ArrayList<Person>) Ognl.getValue("#list.{$ #this.id > 2}",context, list);System.out.println(list2);System.out.println(list3);System.out.println(list4);System.out.println(list5);System.out.println(list6);//[1, 2, 3, 4]//[1-name1, 2-name2, 3-name3, 4-name4]//[Person [id=3, name=name3], Person [id=4, name=name4]]//[Person [id=3, name=name3]]//[Person [id=4, name=name4]]// }catch (OgnlException e){e.printStackTrace();}} View Code7. 創(chuàng)建對象
OGNL支持直接使用表達(dá)式來創(chuàng)建對象。主要有三種情況:
構(gòu)造List對象:使用{},中間使用','進(jìn)行分割如{"aa", "bb", "cc"}
構(gòu)造Map對象:使用#{},中間使用',進(jìn)行分割鍵值對,鍵值對使用':'區(qū)分,如#{"key1" : "value1", "key2" : "value2"}
構(gòu)造任意對象:直接使用已知的對象的構(gòu)造方法進(jìn)行構(gòu)造。
示例代碼如下:
@Testpublic void testOgnl6(){try{Map<String, String> map = (Map<String, String>)Ognl.getValue("#{'key1':'value1'}", null);System.out.println(map);List<String> list = (List<String>)Ognl.getValue("{'key1','value1'}", null);System.out.println(list);Object object = Ognl.getValue("new java.lang.Object()", null);System.out.println(object);//{key1=value1}//[key1, value1]//java.lang.Object@dda25b }catch (OgnlException e){e.printStackTrace();}} View Code這篇OGNL的介紹就到這里,本文并沒有把OGNL的所有內(nèi)容都介紹出來,主要介紹了OGNL的一些簡單的知識,后面有時(shí)間的話我會(huì)陸續(xù)介紹OGNL的相關(guān)知識,并且結(jié)合Struts2深入分析下OGNL的構(gòu)成。同樣謝謝大家的閱讀,本人寫博文的時(shí)候難免有錯(cuò)誤的地方,如果大家發(fā)現(xiàn)希望大家給予指正,謝謝。
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/renchunxiao/p/3423299.html
總結(jié)
- 上一篇: LeetCode:Longest Con
- 下一篇: K-Backup备份office文件的具