Struts2的OGNL表達式語言

一.OGNL的概念

OGNL是Object-Graph Navigation Language的縮寫,全稱爲對象圖導航語言,是一種功能強大的表達式語言,它經過簡單一致的語法,能夠任意存取對象的屬性或者調用對象的方法,可以遍歷整個對象的結構圖,實現對象屬性類型的轉換等功能html

Struts 2支持如下幾種表達式語言:java

  1. OGNL(Object-Graph Navigation Language),能夠方便地操做對象屬性的開源表達式語言;
  2. JSTL(JSP Standard Tag Library),JSP 2.0集成的標準的表達式語言;
  3. Groovy,基於Java平臺的動態語言,它具備時下比較流行的動態語言(如Python、Ruby和Smarttalk等)的一些起特性;
  4. Velocity,嚴格來講不是表達式語言,它是一種基於Java的模板匹配引擎,具說其性能要比JSP好。

Struts 2默認的表達式語言是OGNL,緣由是它相對其它表達式語言具備下面幾大優點:數組

  • 支持對象方法調用,如xxx.doSomeSpecial();
  • 支持類靜態的方法調用和值訪問,表達式的格式爲@[類全名(包括包路徑)]@[方法名 | 值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;
  • 支持賦值操做和表達式串聯,如price=100, discount=0.8, calculatePrice(),這個表達式會返回80;
  • 訪問OGNL上下文(OGNL context)和ActionContext;
  • 操做集合對象。

二.OGNL的重要知識點

1.OGNL表達式的計算是圍繞OGNL上下文進行的。
   OGNL上下文實際上就是一個 Map對象,由ognl.OgnlContext類表示。它裏面能夠存放不少個JavaBean對象。它有一個上下文根對象。
   上下文中的根對象能夠直接使用名來訪問或直接使用它的屬性名訪問它的屬性值。不然要加前綴「#key」。
2.Struts2的標籤庫都是使用OGNL表達式來訪問ActionContext中的對象數據的。如:<s:propertyvalue="xxx"/>。
3.Struts2將ActionContext設置爲OGNL上下文,並將值棧做爲OGNL的根對象放置到ActionContext中。
4.值棧(ValueStack) :
   能夠在值棧中放入、刪除、查詢對象。訪問值棧中的對象不用「#」。
   Struts2老是把當前Action實例放置在棧頂。因此在OGNL中引用Action中的屬性也能夠省略「#」。
5.調用ActionContext的put(key,value)放入的數據,須要使用#訪問。

補充:session

(一)對"上下文"概念的理解(百度百科)app

上下文, 英文是context,其完整意思應當是concatenate-text,聯繫文本,在IT行業中譯爲上下文其實並不確切也不容易理解,尤爲是對於初學者,把它翻譯爲「引用池」或者「引用區」更加恰當。
好比在一篇15頁的部門介紹中,中華人民共和國中央廣播電視總局(如下簡稱廣電總局),這裏的如下,就是下文,在第15頁的時候,你看到廣電總局四個字就知道具體是哪一個部門而不會弄混,這就是在上文作了解釋。
在java的JSP中的內置對象中的PageContext,事實上,它就是本頁面的一個單獨的儲存區域,裏面存放的是各個地方(各個範圍)傳過來的屬性的鍵值對的總彙。好比說,從Application裏面存儲了apptime,appname等等屬性,在Session中又存了sessionid sessionstate等等屬性,在request範圍中又存了username,password等屬性的鍵值對,那麼PageContext就會把全部能獲得的屬性所有集中到一個區域裏,你能夠經過這個小容器,接收和調用到各個範圍傳遞過來的屬性,這就是所謂的」上下文「, 你能夠把它記爲」引用池「!
(二)valuestack,stackContext,ActionContext之間的關係

三者之間的關係以下圖所示:框架

relation


  1. ActionContext :一次Action調用都會建立一個ActionContext ,調用:ActionContext context = ActionContext.getContext()
  2. ValueStack :由OGNL框架實現 ,能夠把它簡單的看做一個List
  3. Stack Object:放入stack中的對象,通常是action。
  4. Stack Context(map):stack上下文,它包含一些列對象,包括request/session/attr/application map等。 
  5. EL:存取對象的任意屬性,調用對象的方法,遍歷整個對象結構圖。

ActionContext是Action上下文,能夠獲得request session application。
ValueStack是值棧 存放表單中的值。
Stack Context 棧上下文 也是用來存值的。post

我的見解,action context 是在action中經過actionSupport類來獲取到,主要做用是獲取request之類的對象,然 後valuestack和stack context都是爲了使用OGNL,其中value stack 是stack context的根對象,因此咱們在JSP頁面中訪問value stack的內容時,是不用加#,而若是是訪問stack context的其餘對象則要加上#。性能

因爲值棧是上下文中的 根對象,所以能夠直接訪問。那麼對於值棧中的對象該如何訪問呢?Struts2提供了一個特殊的OGNLPropertyAccessor,它能夠自動查找棧內的全部對象(從棧頂到棧底),直接找到一個具備你所查找的屬性的對象。也就是說,對於值棧中的任何對象均可以直接訪問,而不須要使用「#」。測試

Struts2框架老是把Action實例放在棧頂。由於Action在值棧中,而值棧又是OGNL中的根,因此引用Action的屬性能夠省略「#」標記,這也是爲何咱們在結果頁面中能夠直接訪問Action的屬性的緣由。    
 OGNL的Stack Context裏除了包括ValueStack這個根以外,還包括
一些命名對象,這些對象沒有保存在值棧中,而是保存在ActionContext中,所以訪問這些對象須要使用「#」標記。這些命名對象都是Map類型。 this

  • parameters:用於訪問請求參數。如:#parameters['id']或#parameters.id,至關於調用了HttpServletRequest對象的getParameter()方法。注意,parameters本質上是一個使用HttpServletRequest對象中的請求參數構造的Map對象,一量對象被建立(在調用Action實例以前就已經建立好了),它和HttpServletRequest對象就沒有了任何關係。
  • request對象:用於訪問HttpServletRequest的屬性。例如#request['foo']或者#request.foo,用於返回HttpServletRequest的getAttribute("foo")方法的返回值。
  • session對象:用於訪問HttpSession的屬性。例如#rsession['foo']或者#session.foo,用於返回HttpSession的getAttribute("foo")方法的返回值。
  • application對象:用於訪問ServletContext的屬性,例如#application['foo']或者#application.foo,用於返回ServletContext的getAttribute("foo")方法的返回值。
  • attr對象:該對象將依次搜索以下對象:PageContext、HttpServletRequest、HttpSession、ServletContext中的屬性。

StackContext「根」對象和普通命名對象的區別在於:

  • 訪問StackContext裏的命名對象須要在對象名以前添加#前綴。
  • 當訪問OGNL的Stack Context裏的「根」對象的屬性時,能夠省略對象名。

struts2對OGNL上下文的概念又作了進一步擴充,在struts2中,OGNL上下文一般以下所示:

                        |--request   

                        |   

                        |--application   

                        |   

 context map---|--OgnlValueStack(root) [ user, action, OgnlUtil, ... ]   

                        |   

                        |--session   

                        |   

                        |--attr   

                        |   

                        |--parameters   

 


    在Struts2中,採用標準命名的上下文(Context)來處理OGNL表達式。處理OGNL的頂級對象是一個Map(也叫context map),而OGNL在這個context中就是一個頂級對象(root)。在用法上,頂級對象的屬性訪問,是不須要任何標記前綴的。而其它非頂級的對象 訪問,須要使用#標記。
    Struts2框架把OGNL Context設置爲咱們的ActionContext。而且ValueStack做爲OGNL的根對象。除value stack以外,Struts2框架還把表明application、session、request這些對象的Map對象也放到 ActionContext中去。(這也就是Struts2建議在Action類中不要直接訪問Servlet API的緣由,它能夠經過ActionContext對象來部分代替這些(Servlet API)功能 ,以方便對Action類進行測試!)

3、OGNL中的三個重要符號#、%、$

#符號

#符號的用途通常有三種:

  1. 訪問非根對象屬性,例如#session.msg表達式,因爲Struts 2中值棧被視爲根對象,因此訪問其餘非根對象時,須要加#前綴。實際上,#至關於ActionContext. getContext();#session.msg表達式至關於ActionContext.getContext().getSession(). getAttribute("msg") 。
  2. 用於過濾和投影(projecting)集合,如persons.{?#this.age>25},persons.{?#this.name=='pla1'}.{age}[0]。
  3. 用來構造Map,例如示例中的#{'foo1':'bar1', 'foo2':'bar2'}。

%符號

%符號的用途是在標誌的屬性爲字符串類型時,計算OGNL表達式的值,這個相似js中的eval,很暴力。

$符號

$符號主要有兩個方面的用途:

  1. 在國際化資源文件中,引用OGNL表達式,例如國際化資源文件中的代碼:reg.agerange=國際化資源信息:年齡必須在${min}同${max}之間。
  2. 在Struts 2框架的配置文件中引用OGNL表達式,例如:
    1. <validators>    
    2.     <field name="intb">    
    3.             <field-validator type="int">    
    4.             <param name="min">10</param>    
    5.             <param name="max">100</param>    
    6.             <message>BAction-test校驗:數字必須爲${min}爲${max}之間!</message>    
    7.         </field-validator>    
    8.     </field>    
    9. </validators

4、OGNL使用方式

  • 訪問屬性

    名字屬性獲取:<s:property value="user.username"/><br>

    地址屬性獲取:<s:property value="user.address.addr"/><br>

  • 訪問方法

    調用值棧中對象的普通方法:<s:property value="user.get()"/><br>

  • 訪問靜態屬性和方法

    調用Action中的靜態方法:<s:property value="@struts.action.LoginAction@get()"/>

    調用JDK中的類的靜態方法:<s:property value="@Java.lang.Math@floor(44.56)"/><br>

    調用JDK中的類的靜態方法(同上):<s:property value="@@floor(44.56)"/><br>

    調用JDK中的類的靜態方法:<s:property value="@java.util.Calendar@getInstance()"/><br>

    調用普通類中的靜態屬性:<s:property value="@struts.vo.Address@TIPS"/><br>

  • 訪問構造方法

    調用普通類的構造方法:<s:property value="new struts.vo.Student('李曉紅' , '美女' , 3 , 25).username"/>

  • 訪問數組

    獲取List:<s:property value="testList"/><br>

    獲取List中的某一個元素(可使用相似於數組中的下標獲取List中的內容):

    <s:property value="testList[0]"/><br>

    獲取Set:<s:property value="testSet"/><br>

    獲取Set中的某一個元素(Set因爲沒有順序,因此不能使用下標獲取數據):

    <s:property value="testSet[0]"/><br> ×

    獲取Map:<s:property value="testMap"/><br>

    獲取Map中全部的鍵:<s:property value="testMap.keys"/><br>

    獲取Map中全部的值:<s:property value="testMap.values"/><br>

    獲取Map中的某一個元素(可使用相似於數組中的下標獲取List中的內容):

    <s:property value="testMap['m1']"/><br>

    獲取List的大小:<s:property value="testSet.size"/><br>

  • 訪問集合 – 投影、選擇(? ^ $)

    利用選擇獲取List中成績及格的對象:<s:property value="stus.{?#this.grade>=60}"/><br>

    利用選擇獲取List中成績及格的對象的username:

    <s:property value="stus.{?#this.grade>=60}.{username}"/><br>

    利用選擇獲取List中成績及格的第一個對象的username:

    <s:property value="stus.{?#this.grade>=60}.{username}[0]"/><br>

    利用選擇獲取List中成績及格的第一個對象的username:

    <s:property value="stus.{^#this.grade>=60}.{username}"/><br>

    利用選擇獲取List中成績及格的最後一個對象的username:

    <s:property value="stus.{$#this.grade>=60}.{username}"/><br>

    利用選擇獲取List中成績及格的第一個對象而後求大小:

    <s:property value="stus.{^#this.grade>=600}.{username}.size"/><br>

  • 集合的僞屬性

    OGNL可以引用集合的一些特殊的屬性,這些屬性並非JavaBeans模式,例如size(),length()等等. 當表達式引用這些屬性時,OGNL會調用相應的方法,這就是僞屬性.

     

  •  Lambda   :[…]    格式::[…]

    使用Lambda表達式計算階乘:

    <s:property value="#f = :[#this==1?1:#this*#f(#this-1)] , #f(4)"/><br>

  • OGNL中#的使用 #能夠取出堆棧上下文中的存放的對象.

       

獲取Paraments對象的屬性:<s:property value="#parameters.username"/>

  •  OGNL中%的使用 

     用%{}能夠取出存在值堆棧中的Action對象,直接調用它的方法.

     例如你的Action若是繼承了ActionSupport .那麼在頁面標籤中,用%{getText('key')}的方式能夠拿出國際化信息.

     OGNL中$的使用

    「$」有兩個主要的用途

     用於在國際化資源文件中,引用OGNL表達式

     在Struts 2配置文件中,引用OGNL表達式

 

 值棧

ValueStack對象。這個對象貫穿整個Action的生命週期(每一個Action類的對象實例會擁有一個ValueStack對象)。當Struts 2接收到一個.action的請求後,會先創建Action類的對象實例,但並不會調用Action方法,而是先將Action類的相應屬性放到ValueStack對象的頂層節點(ValueStack對象至關於一個棧)。

在Action中得到ValueStack對象:ActionContext.getContext().getValueStack()

Top語法:使用Top獲取值棧中的第二個對象:<s:property value="[1].top.對象"/>

N語法:使用N獲取值棧中的第二個對象:<s:property value="[1].對象"/>

@語法:調用action中的靜態方法:<s:property value="@vs1@靜態方法"/> vs:值棧 1:表示第一個。

相關文章
相關標籤/搜索