摘要:
雖然我們一般都是通過學(xué)習(xí)MVC框架而結(jié)緣OGNL,但它并沒有與MVC框架緊緊耦合在一起,而是一個以獨立的庫文件出現(xiàn)的一種功能強大的表達式語言,也是字符串與Java對象之間溝通的橋梁。特別地,正因為它的獨立性,使得我們可以十分方便地利用它構(gòu)建我們自己的框架。在充分理解和掌握 OGNL 三要素 后,我們就可以通過簡單一致的語法去存取Java對象樹中的任意屬性、調(diào)用Java對象樹的方法并自動實現(xiàn)必要的類型轉(zhuǎn)化。本文首先概述了Ognl的前世今生,并結(jié)合具體實例和源碼闡述了OGNL的實質(zhì)和OGNL三要素,介紹了對Java對象屬性值的訪問,靜態(tài)、實例和構(gòu)造方法的調(diào)用,對容器的訪問以及對集合的操作等五個方面的介紹,奠定了學(xué)習(xí)OGNL的基礎(chǔ)。
版權(quán)聲明:
本文原創(chuàng)作者:書呆子Rico
作者博客地址:http://blog.csdn.net/justloveyou_/
友情提示:
為了更好地了解 OGNL,筆者將以兩篇博客的篇幅來介紹OGNL:《與MVC框架解耦的OGNL:前世今生及其基本用法》 和 《再述OGNL:在Struts2中的應(yīng)用》。其中,在本文(《與MVC框架解耦的OGNL:前世今生及其基本用法》)中,我們首先介紹了OGNL的前世今生,并結(jié)合具體實例和源碼闡述了OGNL的實質(zhì)、OGNL三要素和用法語法。在此基礎(chǔ)上,本篇的姊妹篇《再述OGNL:在Struts2中的應(yīng)用》詳盡地介紹了OGNL的在Struts2中的應(yīng)用。
一. OGNL 概述
1、OGNL的前世今生
WebWork是建立在稱為XWork的Command模式框架之上的強大的基于Web的MVC框架。關(guān)于WebWork我們大多數(shù)人可能不太熟悉,最多只是有一種在哪里見過的感覺,但是我一提Struts2,估計大家就能想起來了。眾所周知,Struts2是Struts的下一代產(chǎn)品,是在Struts1和WebWork的技術(shù)基礎(chǔ)上進行了合并的全新框架。需要特別注意的是,全新的Struts2的體系結(jié)構(gòu)與Struts1差別巨大,因為Struts2是以WebWork為核心的,繼承了更多的WebWork血統(tǒng)。
實際上,WebWork 已經(jīng)完全從Web層脫離出來的一個非常優(yōu)秀的框架,其提供了很多核心的、Struts2還在使用的功能,包括前端攔截器(interceptor)、運行時表單屬性驗證、類型轉(zhuǎn)換、IoC(Inversion of Control)容器等,其中就有我們今天的主角,強大的表達式語言 —— OGNL(Object Graph Notation Language)。
2、OGNL 帶給我們的實惠
OGNL 是 Object Graph Navigation Language 的縮寫,全稱為 對象圖導(dǎo)航語言,是一種功能強大的 表達式語言。它通過簡單一致的語法,可以存取Java對象樹中的任意屬性、調(diào)用Java對象樹的方法,并能夠自動實現(xiàn)必要的類型轉(zhuǎn)化。更形象地說,如果我們把OGNL表達式看做是一個帶有語義的字符串,那么OGNL無疑是這個語義字符串與Java對象之間溝通的橋梁。
我們知道,在我們使用 MVC 架構(gòu)模式進行開發(fā)Web應(yīng)用時,數(shù)據(jù)往往需要在各層之間進行流轉(zhuǎn)。由于數(shù)據(jù)在不同層次中的表現(xiàn)形式不盡相同,所以這種流轉(zhuǎn)會很麻煩,特別是在Controller與View之間進行流轉(zhuǎn)。實際上,數(shù)據(jù)在Controller層與View層之間流轉(zhuǎn)的真正痛點就在于:數(shù)據(jù)在View層(視圖頁面)的表現(xiàn)形式是一個扁平的、不帶任何數(shù)據(jù)類型的字符串,而在Controller層(Java世界)完全可以表現(xiàn)為一個具有豐富數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)類型的Java對象,正是由于這種數(shù)據(jù)表現(xiàn)形式的差異,導(dǎo)致我們手工執(zhí)行這種轉(zhuǎn)換將是一項非常復(fù)雜、低效的工作。正因為如此,為了更好地解決數(shù)據(jù)在不同層之間的數(shù)據(jù)流轉(zhuǎn)問題,作為一個優(yōu)秀成熟的框架,Struts2 集成了 WebWork 中的 OGNL 來幫助我們解決個問題。因此,當(dāng)我們在使用Struts2時,會發(fā)現(xiàn)OGNL充斥在前后臺數(shù)據(jù)傳遞與存儲的方方面面,也給我們帶來了極大的方便。
Ps:更多關(guān)于 MVC框架數(shù)據(jù)流轉(zhuǎn)問題與OGNL在Web中的魅力 等內(nèi)容請讀者移步本文的姊妹篇《再述OGNL:在Struts2中的應(yīng)用》。
3、小結(jié)
OGNL是模板語言的一個重要補充,對表現(xiàn)層技術(shù)而言是一次里程碑式的進步。在我們常見的視圖組件,包括 Jsp 2.0,Velocity,Jelly 等,雖然都有類似的功能,比如,在 Jsp 2.0 中我們可以使用其提供的 EL 表達式完成類似的功能。但是,OGNL比它們要完善的多得多,而且以一個獨立的庫文件出現(xiàn),十分方便我們構(gòu)建自己的框架。
二. OGNL 深度解讀:從一個例子說起
我們在上文已經(jīng)提到,OGNL 以一個獨立的庫文件出現(xiàn),十分方便我們構(gòu)建自己的框架。那么,我們首先新建一個Java Project,然后從Struts2的相關(guān)依賴包中導(dǎo)入 ognl-x.x.xx.jar (本人使用的struts-2.1.6中的ognl-2.6.11.jar),搭建完畢后項目結(jié)構(gòu)如下:
Ps:若讀者不知如何重現(xiàn)筆者獲取OGNL的jar包的過程,請筆者移步我的博文《Struts2 實戰(zhàn):從 登錄Demo 看 Struts2 應(yīng)用開發(fā)》去詳細(xì)了解其獲取過程,此不贅述。另外,由于OGNL是Apache開源項目的子項目,所以我們可以從 Apache Commons 下載OGNL的jar包。
1、OGNL應(yīng)用實例
上述的Java Project包含兩個JavaBean類和一個OGNL測試類,我們將圍繞這個Project展開對OGNL的介紹。我們先看一下該Project中各個類的源碼:
(1). 兩個JavaBean
package cn.tju.edu.rico.test;
import java.util.HashSet;
import java.util.Set;
// Java Bean : Student
public class Student {
private College College;
private String name;
private String gentle;
private double height;
private int age;
// 無參構(gòu)造器
public Student() {
}
public Student(String name, int age, double height) {
super();
this.name = name;
this.height = height;
this.age = age;
}
//getter & setter
public College getCollege() {
return College;
}
public void setCollege(College College) {
this.College = College;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGentle() {
return gentle;
}
public void setGentle(String gentle) {
this.gentle = gentle;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", height=" + height + ", age=" + age
+ "]";
}
}
// Java Bean : College
class College {
private String name;
private Set<Student> Students = new HashSet<Student>();
// 無參構(gòu)造器
public College() {
}
//getter & setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Student> getStudents() {
return Students;
}
public void setStudents(Set<Student> Students) {
this.Students = Students;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
(2). OGNL測試類
package cn.tju.edu.rico.test;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OGNLTest {
public static void main(String[] args) throws OgnlException {
// 新建一個學(xué)校對象
College college = new College();
college.setName("TJU");
// 新建一個學(xué)生對象
Student stu = new Student();
stu.setName("Rico");
// 構(gòu)建一個OgnlContext對象 ,并將上述學(xué)校、學(xué)生對象放入Ognl上下文環(huán)境(本質(zhì)是一個Map)中
OgnlContext context = new OgnlContext();
context.put("college", college);
context.put("stu", stu);
// 將學(xué)生設(shè)置為根對象
context.setRoot(stu);
// 構(gòu)建Ognl表達式的樹狀表示
Object expression1 = Ognl.parseExpression("#college.name");
Object expression2 = Ognl.parseExpression("name");
Object expression3 = Ognl.parseExpression("#stu.name");
// 根據(jù)Ognl表達式給Java對象設(shè)置值,將TJU改為NEU
Ognl.setValue(expression1, context, context.getRoot(), "NEU");
// 根據(jù)Ognl表達式獲取Java對象的(屬性)值
Object collegeName = Ognl.getValue(expression1, context,
context.getRoot());
Object stuName2 = Ognl
.getValue(expression2, context, context.getRoot());
Object stuName3 = Ognl
.getValue(expression3, context, context.getRoot());
System.out.println(collegeName);
System.out.println(stuName2);
System.out.println(stuName3);
}
}/* Output:
NEU
Rico
Rico
*///:~
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
上面的輸出結(jié)果對我們來說一點也不意外,因為在Struts2中,我們常常使用上述方式訪問Stack Context(Action Context)及其根對象Value Stack。根據(jù)這個例子我們也能夠看出,所謂的對象圖導(dǎo)航語言本質(zhì)上就是通過 類似”放置到OgnlContext中的名字.屬性名字” 的方式去獲取對應(yīng)對象的屬性值。特別的是,對于根對象的屬性的訪問,我們只需直接利用屬性名字訪問即可,因為根對象只有一個,OGNL會默認(rèn)從OgnlContext中的根對象中去尋找;而對于普通對象的屬性的訪問,我們使用類似”#放置到OgnlContext中的名字.屬性名字”的方式去訪問,這時OGNL在解析表達式的時候發(fā)現(xiàn)表達式開頭帶有”#”,就會去普通對象中去尋找。當(dāng)然,使用這種方式也可以訪問根對象的屬性,但是若在訪問普通對象時不加前綴“#”,將會拋出 ognl.OgnlException。
2、OGNL 三要素
事實上,OGNL表達式的計算是圍繞OGNL上下文(OgnlContext)進行的,而OGNL上下文實際上就是一個Map對象。我們從上述的例子可以看出,無論是setValue方法還是getValue方法,它們均包含三個核心參數(shù),即 tree(OGNL表達式), context(Ognl上下文), root(Ognl上下文的根對象),我們將其稱之為 OGNL的三要素,因為 OGNL 的操作實際上就是圍繞著這三個參數(shù)而進行的。這三者的關(guān)系如下圖所示:
(1).表達式(Expression)
表達式是整個OGNL的核心,所有的OGNL操作都是對表達式解析后進行的。準(zhǔn)確的來說,表達式表達了此OGNL操作的語義,即表明了此OGNL操作“要干什么”。
(2).上下文環(huán)境(Context)
我們在上文提到,所有的OGNL操作都是在一個特定的環(huán)境中進行的,這個環(huán)境就是OGNL的上下文環(huán)境(OGNL Context)。更直白地說,OGNL上下文為OGNL表達式的提供了具體的運行環(huán)境。需要指出的是,我們完全可以像操作Map那樣將一些數(shù)據(jù)設(shè)置到OGNL Context中,以便我們通過OGNL訪問。準(zhǔn)確的來說,Context為OGNL表達式提供了具體環(huán)境,為OGNL操作“提供支持”。
(3).根對象(Root Object)
根對象是OGNL Context中的一員,并且整個OGNL Context最多只允許有一個根對象。也就是說,OGNL Context中共有兩類對象,即 根對象 和 普通對象 ,它們的差異具體表現(xiàn)在訪問方式上,我們針對根對象的存取操作的表達式不需要增加任何前綴(下文會具體提到)。根對象從側(cè)面指明了OGNL操作所針對的對象類別,也就是說,在表達式規(guī)定了“干什么”之后,根對象指明了我們到底“對誰干”(根對象還是普通對象)。
3、OGNL源碼解讀
在上述的例子中,無論是setValue方法還是getValue方法,都是ognl.Ognl類提供的兩個靜態(tài)方法。事實上,在OGNL中,我們最常用到的兩個類是 ognl.Ognl 與 ognl.OgnlContext 。ognl.Ognl類是一個抽象類,并提供了一系列用于解析和解釋執(zhí)行Ognl表達式的方法,而抽象類則是專門用來繼承的;ognl.OgnlContext類則為Ognl表達式提供了一個執(zhí)行環(huán)境,這個類實現(xiàn)了Map接口,所以允許我們通過使用Map的put(key,value)方法向OgnlContext添加各種類型的對象。需要注意的是,在OgnlContext中一共有兩種對象,第一種是根對象,根對象在整個OgnlContext中有且最多只能有一個,我們可以通過調(diào)用OgnlContext.setRoot(obj)設(shè)置根對象。另外一種就是普通對象,它的個數(shù)不受限制。它們最重要的一個區(qū)別是在對象屬性的獲取方式上,前者可直接訪問,后者需使用類似”#放置到OgnlContext中的名字.屬性名字”的方式去訪問 。下面給出了ognl.Ognl 與 ognl.OgnlContext 的聲明方式,關(guān)于它們更多的細(xì)節(jié)本文不在贅述,讀者若想進一步了解,請自行閱讀源碼。
// Ognl 是一個抽象類,而抽象類則是專門用來繼承的
public abstract class Ognl {
...
}
// OgnlContext 是一個Map
public class OgnlContext extends Object implements Map {
...
}
Ps:關(guān)于 抽象類的深層次表述 請讀者移步我的博文《Java 的抽象特性:抽象類與接口深度解析》。
4、小結(jié)
到此為止,我相信通過上面的例子和表述,我們對Ognl表達式有了一個更深入的了解和認(rèn)識。此外,我們知道對于普通對象的屬性的訪問,我們只能使用類似”#放置到OgnlContext中的名字.屬性名字”的方式去訪問,而對于根對象的屬性的訪問,我們可以通過以下兩種方式去訪問:
三. 使用 OGNL 去訪問方法
我們除了利用Ognl表達式訪問對象的屬性,還可以使用它來訪問方法。當(dāng)然,對于方法的訪問,又可以分為 對靜態(tài)方法的訪問、對實例方法的訪問 和 對構(gòu)造方法的訪問,我們先看下面的例子:
package cn.tju.edu.rico.test;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OGNLTest2 {
public static void main(String[] args) throws OgnlException {
// 新建一個學(xué)校對象
College college = new College();
college.setName("NEU");
// 新建一個學(xué)生對象
Student stu = new Student();
stu.setName("Livia");
stu.setCollege(college);
stu.setGentle("boy");
// 構(gòu)建一個OgnlContext對象,并將上述學(xué)校和學(xué)生對象放入Ognl上下文環(huán)境中
OgnlContext context = new OgnlContext();
context.put("college", college);
context.put("stu", stu);
// 將學(xué)生對象設(shè)置為根對象
context.setRoot(stu);
// 訪問實例方法
Object expression1 = Ognl.parseExpression("getGentle()");
Object length1 = Ognl.getValue(expression1, context, context.getRoot());
Object expression2 = Ognl.parseExpression("#college.name.length()");
Object length2 = Ognl.getValue(expression2, context, context.getRoot());
System.out.println(length1);
System.out.println(length2);
// 訪問靜態(tài)方法
Object expression3 = Ognl.parseExpression("@java.lang.Math@max(2,4)");
Object length3 = Ognl.getValue(expression3, context, context.getRoot());
Object expression4 = Ognl
.parseExpression("@java.lang.String@valueOf(name.length())");
Object length4 = Ognl.getValue(expression4, context, context.getRoot());
System.out.println(length3);
System.out.println(length4);
// 訪問構(gòu)造方法:通過Ognl表達式構(gòu)建一個LinkedList對象,注意使用全類名
Object expression5 = Ognl.parseExpression("new java.util.LinkedList()");
List list = (List)Ognl.getValue(expression5, context, context.getRoot());
list.add("list");
list.add("rico");
System.out.println(list);
}
}/* Output:
boy
3
4
5
[list, rico]
*///:~
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
四. 使用 OGNL 去訪問容器對象
我們還可以利用Ognl表達式訪問容器對象,包括數(shù)組,List,Set,Map等,看下面的例子:
package cn.tju.edu.rico.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OGNLTest3 {
public static void main(String[] args) throws OgnlException {
OgnlContext context = new OgnlContext();
// 處理數(shù)組類型
String[] strs = new String[] { "a", "b", "c" };
context.put("strs", strs);
System.out.println(Ognl.getValue("#strs[2]", context, context.getRoot()));
// 處理List類型
List<String> words = new ArrayList<String>();
words.add("rico");
words.add("livia");
words.add("neu");
context.put("words", words);
System.out.println(Ognl.getValue("#words[0]", context,context.getRoot()));
// 處理Map類型
Map<String,String> map = new HashMap<String,String>();
map.put("ad", "d");
map.put("Rico", "China");
map.put("campus", "neu");
context.put("map", map);
System.out.println(Ognl.getValue("#map['Rico']",context, context.getRoot()));
// 處理Set類型:由于Set的無序性,所以不能通過這種訪問Set(只能迭代輸出),會拋出 ognl.NoSuchPropertyException;
Set<String> set = new HashSet<String>();
set.add("rico");
set.add("livia");
set.add("neu");
context.put("set", set);
System.out.println(Ognl.getValue("#set[2]", context, context.getRoot()));
}
}/* Output:
c
rico
China
Exception in thread "main" ognl.NoSuchPropertyException: java.util.HashSet.2
*///:~
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
由于Set是無序的且沒有索引,所以我們只能對其進行迭代輸出。Struts2 提供了一組邏輯控制標(biāo)簽,其中就有iterator,它可以完美完成這件事情。關(guān)于Struts2 的邏輯控制標(biāo)簽的敘述詳見本文的姊妹篇《再述OGNL:在Struts2中的應(yīng)用》。
由于HashSet就是通過HashMap實現(xiàn)的,所以更多關(guān)于 HashSet的了解,讀者可以參考我的博文《Map 綜述(一):徹頭徹尾理解 HashMap》。
五. 使用 OGNL 對容器進行操作
我們還可以利用Ognl表達式對容器對象作一些操作,比如 過濾 和 投影。過濾指的是將原集合中不符合條件的對象過濾掉,然后將滿足條件的對象,構(gòu)建一個新的集合對象返回,Ognl過濾表達式的寫法是:collection.{?|^|$ expression};投影指的是將原集合中所有對象的某個屬性抽取出來,單獨構(gòu)成一個新的集合對象返回,基礎(chǔ)語法為 :collection.{expression}。特別需要注意的是,無論是過濾操作還是投影操作,它們的操作對象和操作結(jié)果都是一個容器。
package cn.tju.edu.rico.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OGNLTest4 {
public static void main(String[] args) throws OgnlException {
Student s1 = new Student("Tom", 22, 170.3);
Student s2 = new Student("Jack", 21, 176.2);
Student s3 = new Student("Tomas", 23, 180.1);
Student s4 = new Student("Lucy", 20, 163.3);
List<Student> stus = new ArrayList<Student>();
Collections.addAll(stus, s1, s2, s3, s4);
// 新建OgnlContext對象
OgnlContext context = new OgnlContext();
context.put("stus", stus);
// 過濾(filtering),collection.{? expression}
// 利用過濾獲取身高在175以上的所有學(xué)生集合
// 輸出結(jié)果:[Student [name=Jack, age=21, height=176.2], Student [name=Tomas, age=23, height=180.1]]
System.out.println(Ognl.getValue("#stus.{? #this.height > 175.0}", context, context.getRoot()));
// 過濾(filtering),collection.{^ expression}
// 利用過濾獲取身高在175以上的所有學(xué)生集合中第一個元素
// 輸出結(jié)果:[Student [name=Jack, age=21, height=176.2]]
System.out.println(Ognl.getValue("#stus.{^ #this.height > 175.0}", context, context.getRoot()));
// 過濾(filtering),collection.{$ expression}
// 利用過濾獲取身高在175以上的所有學(xué)生集合的最后一個元素
// 輸出結(jié)果:[Student [name=Tomas, age=23, height=180.1]]
System.out.println(Ognl.getValue("#stus.{$ #this.height > 175.0}", context, context.getRoot()));
// 投影(projection), collection. {expression}
// 獲取集合中的所有學(xué)生的姓名
// 輸出結(jié)果:[Tom, Jack, Tomas, Lucy]
System.out.println(Ognl.getValue("#stus.{name}", context, context.getRoot()));
}
}/* Output:
[Student [name=Jack, height=176.2, age=21], Student [name=Tomas, height=180.1, age=23]]
[Student [name=Jack, height=176.2, age=21]]
[Student [name=Tomas, height=180.1, age=23]]
[Tom, Jack, Tomas, Lucy]
*///:~
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
六. 總結(jié)
雖然我們一般都是通過學(xué)習(xí)MVC框架而結(jié)緣OGNL,但它并沒有與MVC框架緊緊耦合在一起,而是一個以獨立的庫文件出現(xiàn)的一種功能強大的表達式語言,也是字符串與Java對象之間溝通的橋梁。特別地,正因為它的獨立性,使得我們可以十分方便地利用它構(gòu)建我們自己的框架。在充分理解和掌握 OGNL 三要素 后,我們就可以通過簡單一致的語法去存取Java對象樹中的任意屬性、調(diào)用Java對象樹的方法并自動實現(xiàn)必要的類型轉(zhuǎn)化。本文首先概述了Ognl的前世今生,并結(jié)合具體實例和源碼闡述了OGNL的實質(zhì)和OGNL三要素,介紹了對Java對象屬性值的訪問,靜態(tài)、實例和構(gòu)造方法的調(diào)用,對容器的訪問以及對集合的操作等五個方面的介紹,奠定了學(xué)習(xí)OGNL的基礎(chǔ)。
七. 更多
更多關(guān)于 MVC框架數(shù)據(jù)流轉(zhuǎn)問題與OGNL在Web中的魅力 等內(nèi)容請讀者移步本文的姊妹篇《再述OGNL:在Struts2中的應(yīng)用》。
更多關(guān)于 Struts2的概述及其與Struts1.x差異 請讀者移步我的博文《 Struts1與Struts2的區(qū)別和對比(深度好文)》。
更多關(guān)于 抽象類的深層次表述 請讀者移步我的博文《Java 的抽象特性:抽象類與接口深度解析》。
由于HashSet就是通過HashMap實現(xiàn)的,所以更多關(guān)于 HashSet的了解,讀者可以參考我的博文《Map 綜述(一):徹頭徹尾理解 HashMap》。
更多關(guān)于Struts2的的介紹請見我的專欄《Java Web 成神之路》。本專欄全面記錄了Java Web開發(fā)相關(guān)知識,不但包括對http, servlet,session等基礎(chǔ)知識的講解,還包括對流行框架(SSM,SpringMVC等)、中間件(Redis等)等進階知識的深入分析。筆者將持續(xù)跟進最新Web技術(shù),期望對大家能夠起到拋磚引玉的效果。
引用
OGNL表達式語言詳解
Struts2中的OGNL詳解
ognl概念和原理詳解
ognl 詳解
|