OGNL
一、值棧
我們在struts——helloWorld中的示例程式中,使用了
${productName}
讀取productName 值,實際上該屬性并不在request 等域對象中,而是從值棧中擷取的。
值棧,ValueStack:
可以從ActionContext中擷取值棧對象。
值棧可以分為兩個邏輯部分:
- Map棧:實際上是OgnlContext類型。也是對ActionContext的一個引用。裡面儲存各種Map:
,requestMap
,sessionMap
,applicationMap
,parametersMap
.attr
- 對象棧:實際上是CompoundRoot類型,是一個使用ArrayList定義的棧。裡面儲存着各種和目前Action執行個體相關的對象。是一個資料結構意義的棧。
ValueStack(值棧): 貫穿整個 Action 的生命周期(每個 Action 類的對象執行個體都擁有一個 ValueStack 對象). 相當于一個資料的中轉站. 在其中儲存目前 Action 對象和其他相關對象.
Struts 架構把 ValueStack 對象儲存在名為 “struts.valueStack” 的請求屬性中。
在 ValueStack 對象的内部有兩個邏輯部分:
- ObjectStack: Struts 把 Action 和相關對象壓入 ObjectStack 中
- ContextMap: Struts 把各種各樣的映射關系(一些 Map 類型的對象) 壓入 。ContextMap 中. 實際上就是對 ActionContext 的一個引用
Struts 會把下面這些映射壓入 ContextMap 中
- parameters: 該 Map 中包含目前請求的請求參數
- request: 該 Map 中包含目前 request 對象中的所有屬性
- session: 該 Map 中包含目前 session 對象中的所有屬性
- application:該 Map 中包含目前 application 對象中的所有屬性
- attr: 該 Map 按如下順序來檢索某個屬性: request, session, application
二、OGNL
在 JSP 頁面上可以可以利用 OGNL(Object-Graph Navigation Language: 對象-圖導航語言) 通路到值棧(ValueStack) 裡的對象屬性。
若希望通路值棧中 ContextMap 中的資料,需要給OGNL表達式加上一個字首字元
#
。如果沒有字首字元#,搜尋将在ObjectStack裡進行。
1. property标簽
Struts 的 property 标簽用來輸出值棧中的一個屬性值.
jsp檔案上面需要導入标簽庫:
<%@ taglib prefix="s" uri="/struts-tags" %>
2. 讀取ObjectStack裡對象的屬性
- 想要通路ObjectStack裡對象的屬性。可以使用以下幾種形式之一:
object.propertyName object['propertyName'] object["propertyName"]
- ObjectStack 裡的對象可以通過一個從零開始的下标來引用。 ObjectStack 裡的棧頂對象可以用 [0] 來引用, 它下面的那個對象可以用 [1] 引用.。若希望傳回棧頂對象的 message 屬性值:
或[0].message
或[0]["message"]
,結合property标簽,可以寫成:[0]['message']
或者<s:property value="[0].message" />
<s:property value="message" />
- 若在指定的對象裡沒有找到指定的屬性, 則到指定對象的下一個對象裡繼續搜尋. 即 [n] 的含義是從第 n 個開始搜尋, 而不是隻搜尋第 n 個對象
- 若從棧頂對象開始搜尋, 則可以省略下标部分
預設情況下,Action 對象會被Struts2自動的放到值棧的棧頂。
3. 讀取Context Map棧裡面的屬性
若想通路 ContextMap 裡的某個對象的屬性, 可以使用以下幾種形式之一:
#object.propertyName
#object['propertyName']
#object["propertyName"]
示例:
- 傳回 session 中的 code 屬性:
#session.code
- 傳回 request 中的 customer 屬性的 name 屬性值:
#request.customer.name
- 傳回域對象(按 request, session, application 的順序)的 lastAccessDate 屬性:
#attr.lastAccessDate
4. 調用字段和方法
可以利用 OGNL 調用
- 任何一個 Java 類裡的靜态字段或方法.
- 被壓入到 ValueStack 棧的對象上的公共字段和方法.
預設情況下, Struts2 不允許調用任意 Java 類靜态方法, 需要重新設定
struts.ognl.allowStaticMethodAccess
标記變量的值為 true.
調用靜态字段或方法需要使用如下所示的文法:
-
@[email protected]:
例如:
@[email protected]
-
@[email protected](argumentList):
例如:
@[email protected]()
調用一個執行個體字段或方法的文法, 其中 object 是 Object Stack 棧裡的某個對象的引用:
- object.fieldName:
[0].datePattern
- object.methodName(argumentList):
[0].repeat(3, “Hello”);
5. 通路數組類型的屬性
- 有些屬性将傳回一個對象數組而不是單個對象, 可以像讀取任何其他對象屬性那樣讀取它們。這種數組型屬性的各個元素以逗号分隔, 并且不帶方括号。
- 可以使用下标通路數組中指定的元素:
colors[0]
- 可以通過調用其 length 字段查出給定數組中有多少個元素:
colors.length
6. 通路List類型的數組
- 有些屬性将傳回的類型是 java.util.List, 可以像讀取任何其他屬性那樣讀取它們. 這種 List 的各個元素是字元串, 以逗号分隔, 并且帶方括号
- 可以使用下标通路 List 中指定的元素:
colors[0]
- 可以通過調用其 size 方法或專用關鍵字 size 的方法查出給定List 的長度:
或colors.size
colors.size()
- 可以通過使用 isEmpty() 方法或專用關鍵字 isEmpty 來得知給定的 List 是不是空.
或colors.isEmpty
colors.isEmpty()
- 還可以使用 OGNL 表達式來建立 List, 建立一個 List 與聲明一個 Java 數組是相同的:
{“Red”, “Black”, “Green”}
7. 通路Map類型的屬性
- 讀取一個 Map 類型的屬性将以如下所示的格式傳回它所有的鍵值對:
{ key-1=value-1, key-2=value-2,... key-n=value-n,}
- 若希望檢索出某個 Map 的值, 需要使用如下格式:
map[key]
- 可以使用
或size
得出某個給定的 Map 的鍵值對的個數size()
- 可以使用
或isEmpty
檢查某給定 Map 是不是空.isEmpty()
- 可以使用如下文法來建立一個 Map:
#{ key-1:value-1, key-2:value-2,... key-n:value-n,}
8. 使用EL通路值棧中對象的屬性
<s:property value=“fieldName”>
也可以通過 JSP EL 來達到目的:
${fieldName}
原理: Struts2 将包裝
HttpServletRequest
對象後的
org.apache.struts2.dispatcher.StrutsRequestWrapper
對象傳到頁面上, 而這個類重寫了
getAttribute()
方法.
END.