1. 程式人生 > >struts2(六)之ognl表達式與ActionContext、ValueStack

struts2(六)之ognl表達式與ActionContext、ValueStack

誤區 共享 not in 1.2 domu oot 數學 request png

前言

  前面已經把struts2講內容說了一半了,我寫的很詳細,希望對博友們有幫助。

一、OGNL表達式語言概述

1.1、OGNL表達式簡介

  百度上是這樣說:

  技術分享

  OGNL是Object-Graph Navigation Language的縮寫,它是一個單獨的開源項目。Struts2框架使用OGNL作為默認的表達式語言。

  它是一種功能強大的表達式語言,通過它簡單一致的表達式語法,可以存取對象的任意屬性,調用對象的方法,遍歷整個對象的

  結構圖,實現字段類型轉化等功能。它使用相同的表達式去存取對象的屬性。

1.2、OGNL功能概述

  對OGNL這5個作用進行講解:

    1)存取對象的任意屬性,簡單說就是對javabean進行操作(重要)

    2)調用對象方法

    3)調用類的靜態方法

    4)索引數組元素

    5)操作集合(重 要)

1.4、OGNL表達式使用格式

  操作之前必須知道如何使用OGNL表達式,並且了解OGNL表達式的取值範圍只能在其context和root中,格式為:

    Ognl.getValue(expression,context,root);

         //expression:為我們編寫的ognl表達式,從後兩個參數中獲取值,獲取規則會從下面的例子中詳細講解

         //context:ognl的上下文,類型為map,

         //root:ognl的根,可以為javabean、list、map、.... 等等很多值

二、OGNL功能實現

2.1、對javabean進行操作

  1)User.java

    技術分享

  2)Address.java

    技術分享

  3)獲取javabean中的屬性值

    技術分享

  4)獲取javabean中的對象的屬性值

    技術分享

  5)對javabean中的屬性進行賦值操作

    技術分享

2.2、調用對象方法

    技術分享

2.3、調用類的靜態方法或屬性

  這裏獲取靜態方法和靜態變量,不受方法或屬性是否在root或者上下文中的限制。
  編寫user對象放入root中只是為了滿足使用Ognl的條件,沒有別的作用。

  1)訪問靜態方法

    調用系統的類的靜態方法,調用編寫的類的靜態方法,都是一樣的。

    格式:@包名+類名@靜態方法

    例如:@java.util.UUID@randomUUID()

  2)訪問靜態變量

    格式:@包名+類名@靜態變量名

    例如:@java.lang.Math@PI

    技術分享

    結果:

    技術分享

2.4、索引數組元素

  技術分享

2.5、操作集合

  1)操作list集合

    list結合本質就是一個數組,所以從list中讀取數據跟對數組的操作是一樣的。

    技術分享

  2)操作map集合

    取root下的map集合中的value值

    格式:key   直接寫上key,就能找到對應的value值,如果value值是一個對象,那麽通過“.”來獲取中的屬性。

    如果想獲取上下文中的屬性,因為上下文就是一個map,為了區分是從root下取還是從上下文中取。使用“#”區分

    格式:#key

    技術分享

  3)創建list集合

    格式:{xxx,xxxx,xxxxx......}

    技術分享

  4)創建map集合

    格式:#{‘key‘:‘value‘,‘key‘:‘value‘}

    技術分享

2.6、其他用法

  使用數學運算符,使用“,”號連接表達式,in與not in運算符,投影、過濾等操作就不講解了,都非常簡單,重點掌握上面的即可。

三、OGNL與Struts2的結合

  從上面的例子中我們可以看出來OGNL的功能非常的強大,能對對象進行存取,能操作少數組、集合。那在struts2中是如何使用的呢?

  OGNL中的上下文即struts2中的actionContext

  OGNL中的root即struts2中的valueStack

  ctionContext和valueStack是什麽,他們之間什麽關系?

3.1、ActionContext

  充當OGNL的context。是action的上下文,也可以叫做action的數據中心,本質是一個map,在其中,所有的數據都存放在這裏,

  那其中到底存放了哪些東西呢,actionContext中存放數據的方式又是怎樣的?

  actionContext是一個map,所以其中都是以鍵值對的形式存儲對象,如下圖所示:

  技術分享

  request、session、application這種我們熟知的作用域,註意是作用域,而不是對象,

  paramters:這個是表單提交的參數,全部都會放到這個map中,

  attr(attributes):三個作用域所有的屬性都會放在該map下,如果有重復的,那麽以request域中的為準

  VALUE_STACK:值棧,存放著valueStack對象,也就是說,通過ActionContext能夠獲取到valueStack

  如果我們使用actionContext.put(); 那麽會將該鍵值對直接放入到ActionContext下。

  註意:除了request外,其他都可以直接通過getXxx()獲得。而想要獲取request作用域,必須通過key值的方式來獲取。ActionContext.getContext().get("request");

     為什麽這樣呢?因為struts2對request進行了增強。從這裏actionContext中是不能直接獲取到的,request進行了怎樣的增強呢?比如在actionContext中put了

    一個普通的key和value,該鍵值對並沒有在request域中,但是在jsp中,通過在request域查找key,也能找到該鍵值對,底層進行了兩步:第一步:從request域

    中查找數據,第二步:如果沒有找到,將從值棧中執行findValue()。  這樣就解釋了為什麽通過ActionContext不能直接獲取request,並且為什麽不在request作

    用域中的數據,而通過在request域中查找也能夠獲取到。

3.2、ValueStack

  值棧,本質是一個ArrayList,作用,充當ognl的root,給一次請求中共享數據的功能

  技術分享

  root:源碼中的名稱為CompoundRoot,它也是一個棧,而每次值棧中入棧和出棧等操作其實就是對CompoundRoot進行對應的操作。

  Context:對actionContext的引用,也就是通過valueStack也能夠獲取到上下文,通過getContext();

  在我們訪問一個action時,會將action加入到棧頂,也就是action會在CompoundRoot的棧頂,而我們提交的各種表單參數(充當了ognl表達式)會

  在valueStack從頂向下查找對應的屬性進行賦值。這就是值棧的作用。

  值棧的操作

    這裏提一下,知道了值棧的內部結構圖,那麽就好理解了。

    action中手動向valueStack中放數據。

      ActionContext.getContext().getValueStack().push(xxx);  //一般是javabean,這樣放是放在root中,因為push操作是對棧進行操作,也就是對root進行操作

      ActionContext.getContext().getValueStack().set(key,value);  //任意值,以key-value的形式放入到了root中。

    jsp獲取

      push存放,在root下,直接使用屬性獲取即可

      set存放,通過屬性也可以直接獲得。這裏要排除一個誤區,就是不要覺得set方式是以鍵值對的方式存放,就覺得是放入了context中,並沒有,還是在root中鍀

    context操作

      ActionContext.getContext().put(key,value);  //存放在actionContext中,也就是OGNL的context中

    JSP獲取:三種方式進行獲取

      #key獲取。  

      直接使用key獲取,因為值棧中也有context。只不過要從棧頂中的root開始找,然後在從context中查找

      #request獲取。因為struts2對request進行了增強,如果request域中找不到,則使用findValue(),從值棧中的root開始一路往下找。

3.3、ActionContext和valueStack的關系(重要)

  技術分享

  也就是說,通過valueStack可以獲取到actionContext,通過ActionContext也可以獲取到valueStack。  

  valueStack是對root進行操作,而actionContext是對context進行操作。(root和context是OGNL中的根和上下文)

  獲取值棧的方式:

    ActionContext.getContext.getValueStack();//常用

    ActionContext.getContext.get("VALUE_STACK");

    request.getAttribute("VALUE_STACK");    //這個為什麽可以?因為request進行了增強。詳情看上面的解釋。

  獲取actionContext的方式

    ActionContext.getContext();  //常用

    valueStack.getContext();

四、struts2中使用OGNL表達式獲取數據

4.1、jsp頁面中

  大部分都會在這裏使用,因為jsp就是顯示數據的地方,在struts2中有很多s標簽,通過s標簽和OGNL表達式一起配置使用,就能拿到想要的數據了

  而OGNL的表達式的編寫在最開始就已經講解過了,context就是actionContext,root就是valueStack,剩下表達式就看我們需要什麽了。

4.2、在struts.xml中

  在struts.xml中有時候也需要用到OGNL表達式去拿一些數據。比如,在result中設置stream時,就需要從action中獲取流,而action可以看成是javabean,

  又在棧頂,所以直接使用OGNL表達式就能夠獲取到,但是註意特殊的,如果在你直接編寫ognl表達式時struts2不能夠區分出這是ognl表達式還是普通文

  本,那麽就需要使用${}來表明該段文本是ognl表達式。

  技術分享

struts2(六)之ognl表達式與ActionContext、ValueStack