一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

與MVC框架解耦的OGNL:前世今生及其基本用法

 hkls0003 2018-06-05

摘要:

  雖然我們一般都是通過學(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)如下:

                Image 4.png-8.8kB

  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 {
    ...
}
  • 1
  • 2
  • 3
  • 4
// OgnlContext 是一個Map
public class OgnlContext extends Object implements Map {
    ...
}
  • 1
  • 2
  • 3
  • 4

  Ps:關(guān)于 抽象類的深層次表述 請讀者移步我的博文《Java 的抽象特性:抽象類與接口深度解析》。


4、小結(jié)

  到此為止,我相信通過上面的例子和表述,我們對Ognl表達式有了一個更深入的了解和認(rèn)識。此外,我們知道對于普通對象的屬性的訪問,我們只能使用類似”#放置到OgnlContext中的名字.屬性名字”的方式去訪問,而對于根對象的屬性的訪問,我們可以通過以下兩種方式去訪問:

  • 直接利用屬性名字訪問;

  • 類似”#放置到OgnlContext中的名字.屬性名字”的方式去訪問;
     
      
    下文我們將著重講述Ognl的基本用法,拋開MVC框架單獨了解它的用法便于我們進一步理解Ognl在Struts2中的使用方式。


三. 使用 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 詳解

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    亚洲欧美一二区日韩高清在线| 日韩特级黄片免费在线观看| 日韩丝袜诱惑一区二区| 欧美三级不卡在线观线看| 丰满人妻熟妇乱又伦精另类视频| 伊人久久五月天综合网| 午夜直播免费福利平台| 免费观看一级欧美大片| 东京热男人的天堂社区| 99久久精品国产日本| 日本视频在线观看不卡| 国产又黄又猛又粗又爽的片| 国产不卡的视频在线观看| 国产二级一级内射视频播放| 午夜福利大片亚洲一区| 福利在线午夜绝顶三级| 亚洲精品高清国产一线久久| 国产内射一级一片内射高清视频| 大香伊蕉欧美一区二区三区| 九九热国产这里只有精品| 亚洲国产另类久久精品| 国产午夜在线精品视频| 欧美一级黄片欧美精品| 久久人人爽人人爽大片av| 国产成人精品在线一区二区三区| 日本午夜福利视频免费观看| 99热在线播放免费观看| 日韩偷拍精品一区二区三区| 日韩一区欧美二区国产| 欧美区一区二在线播放| 肥白女人日韩中文视频| 沐浴偷拍一区二区视频| 欧美日韩在线视频一区| 国产精品一区二区不卡中文| 亚洲日本中文字幕视频在线观看 | 久久人妻人人澡人人妻| 日韩精品一级一区二区| 日韩成人动画在线观看| 嫩草国产福利视频一区二区| 精品午夜福利无人区乱码| 国产精品日韩精品一区|