參考http://struts.apache.org/2.x/docs/ognl-basics.html 和 http://struts.apache.org/2.x/docs/ognl.html
OGNL——Object Graph Navigation Language,參考 http://www.ognl.org/
一.Xwork的OGNL
在Struts2裏邊的OGNL是基於XWork的。XWork的OGNL和普通意義上的OGNL有一些差異,首先最大的差異就是OGNL只提供了一個根對象(root),而Xwork提供了一個ValueStack,這是Struts2的OGNL的默認root。另外,XWork提供了本身獨特的OGNL PropertyAccessor自動從頂向下的查找Stack中符合條件的對象屬性。
好比說,有兩個對象Animal和Person,兩個對象都提供了name屬性,同時Animal有species屬性,Person有salary屬性。假定Animal在stack的頂端。html
species // call to animal.getSpecies() salary // call to person.getSalary() name // call to animal.getName() because animal is on the top
從這裏能夠看到從頂向下查找的做用。在XWork中,咱們能夠用[n].name這種方式來訪問不一樣層次的同名屬性。n必須是正整數。apache
[0].name // call to animal.getName() [1].name // call to person.getName()
訪問對象的靜態屬性的時候,OGNL默認採用以下的方式session
@some.package.ClassName@FOO_PROPERTY @some.package.ClassName@someMethod()
而XWork訪問靜態屬性的方式有所差別:經過@vs來訪問。vs表示的意思是valueStack。而且,能夠在vs後面跟隨數字來表示其訪問stack的層次。app
@vs@FOO_PROPERTY @vs@someMethod() @vs1@FOO_PROPERTY @vs1@someMethod() @vs2@BAR_PROPERTY @vs2@someOtherMethod()
二.Struts2中的OGNL
在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對象來部分代替這些功能,以方便對Action類進行測試!)
Action的實例,老是放到value stack中。由於Action放在stack中,而stack是root(根對象),因此對Action中的屬性的訪問就能夠省略#標記。可是,要訪問ActionContext中其它對象的屬性,就必需要帶上#標記,以便讓OGNL知道,不是從根對象,而是從其它對象中去尋找。
那麼訪問Action中的屬性的代碼就能夠這樣寫框架
<s:property value="postalCode"/>
其它ActionContext中的非根對象屬性的訪問要像下面這樣寫:
<s:property value="#session.mySessionPropKey"/> or
<s:property value="#session['mySessionPropKey']"/> or
<s:property value="#request['myRequestPropKey']"/>
對Collection的處理,內容就很簡單。
<s:select label="label" name="name" list="{'name1','name2','name3'}" value="%{'name2'}" />
這是處理List。這個代碼在頁面上創建一個下拉選項,內容是list中的內容,默認值是name2.
處理mappost
<s:select label="label" name="name" list="#{'foo':'foovalue', 'bar':'barvalue'}" />測試
須要注意的是,判斷一個值是否在collection中。咱們要使用in或者not in來處理。
<s:if test="'foo' in {'foo','bar'}">
muhahaha
</s:if>
<s:else>
boo
</s:else>
另外,可使用通配符來選擇collection對象的子集。
?——全部匹配選擇邏輯的元素
^——只提取符合選擇邏輯的第一個元素
$——只提取符合選擇邏輯的最後一個元素
person.relatives.{? #this.gender == 'male'}this