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"]
或[0]['message']
,結合property標籤,可以寫成:<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.
調用靜態字段或方法需要使用如下所示的語法:
- @fullyQualifiedClassName@fieldName:
例如:@java.util.Calendar@DECEMBER
- @fullyQualifiedClassName@methodName(argumentList):
例如:@app4.Util@now()
調用一個實例字段或方法的語法, 其中 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
或size()
得出某個給定的 Map 的鍵值對的個數 - 可以使用
isEmpty
或isEmpty()
檢查某給定 Map 是不是空. - 可以使用如下語法來創建一個 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.