tags: Struts2
什麼是OGNL表示式?
OGNL是Object Graphic Navigation Language 是操作物件屬性的開源表示式。 Struts2框架使用OGNL作為預設的表示式語言。
為什麼我們學習OGNL
在學習JSP的時候,我們已經學習過了EL表示式。EL表示式用起來也十分簡單...我們在Struts2框架中也是可以使用EL表示式的...那麼OGNL表示式好在哪裡呢??
- 支援物件方法呼叫,如xxx.doSomeSpecial()
- 支援類靜態的方法呼叫和值訪問,表示式的格式【例如:"@@floor(10.9)"就是呼叫Math.floor()的方法了】
- 支援賦值操作和表示式串聯【這個其實EL表示式也能做】
- 訪問OGNL上下文(OGNL context)和ActionContext
- 操作集合物件【EL只能遍歷集合,OGNL可以建立集合】
OGNL是Struts2的預設表示式語言,OGNL是配搭Strut2的標籤使用的..我們學習了OGNL表示式,就可以更好地理解Struts2標籤的執行以及Struts2內部的儲存結構.
valueStack物件
在講解OGNL表示式之前,我們先來看看valueStack物件...valueStack是Struts2資料儲存的核心...我們首先要知道資料是怎麼存的,存到哪裡,然後才講解OGNL表示式是怎麼取出資料的。
valueStack也被稱作值棧物件..
- 當使用者訪問Action,都會建立一個Action物件,ActionContext物件、valueStack物件..
- Struts2把Action物件放進valueStack物件之中。
- 將valueStack放進request域中,傳入JSP頁面(key: struts.valueStack)
- JSP頁面就可以使用OGNL表示式獲取值棧中的資料了!
獲取valueStack物件
- 在Action中我們可以手動獲取值棧物件,有兩種方式獲取:
//獲取值棧物件的2種方式
private void getVs() {
// 獲取值棧物件,方式1:
HttpServletRequest request = ServletActionContext.getRequest();
ValueStack vs1 = (ValueStack) request.getAttribute("struts.valueStack");
// 獲取值棧物件,方式2:
ActionContext ac = ActionContext.getContext();
ValueStack vs2 = ac.getValueStack();
System.out.println(vs1 == vs2);//true
}
複製程式碼
valueStack內部儲存結構
上面已經說了,使用者訪問Action時,會建立Action物件,valueStack物件。Struts2內部會將Action物件存到valueStack物件之中...那麼valueStack的儲存結構是什麼樣的呢???我們來看看
CompoundRoot
Action物件和Action的成員屬性等值都是存到CompoundRoot下的.該CompoundRoot繼承著ArrayList,因此它是List結構的
public class CompoundRoot extends ArrayList {}
複製程式碼
OgnlContext
OgnlContext物件儲存著相關的域物件:request、response、session等資料,實現Map集合,是Map結構..
為了讓request、response等域物件可以儲存多個值,值也是使用Map結構...
public class OgnlContext implements Map {}
複製程式碼
小總結
CompoundRoot儲存著這樣的資料:
- Action物件以及Action物件的成員屬性資料
- 使用ValueStack物件.push()進去的資料
- 使用ValueStack物件.set()進去的資料
- 其他代理物件的資料
OgnlContext儲存著這樣的資料:
- 維護了CompoundRoot中所有的資料
- request、response等域物件所有的資料
OGNL表示式取值
- Struts2會將valueStack物件封裝進request物件域中,傳入JSP頁面。
- valueStack儲存著OgnlContext物件。
- OgnlContext物件維護了CompoundRoot物件的資料
- CompoundRoot儲存著Action等資料
也就是說通過OgnlContext物件可以獲取大部分我們需要的資料了。
那麼OGNL表示式是怎麼取出OgnlContext物件中資料的呢??下面我們通過硬編碼的方式來講解:
/**
* 1. Ognl表示式語言語言取值,取非根元素的值,必須用#號
* @throws Exception
*/
@Test
public void testOgnl() throws Exception {
// 建立一個Ognl上下文物件
OgnlContext context = new OgnlContext();
// 放入資料
User user = new User();
user.setId(100);
user.setName("Jack");
// 【往非根元素放入資料, 取值的時候表示式要用"#"】
context.put("user", user);
// 獲取資料(map)
// 先構建一個Ognl表示式, 再解析表示式
Object ognl = Ognl.parseExpression("#user.name");
Object value = Ognl.getValue(ognl, context, context.getRoot());
System.out.println(value);
}
/**
* 2. Ognl表示式語言語言取值,取根元素的值,不用帶#號
* @throws Exception
*/
@Test
public void testOgn2() throws Exception {
// 建立一個Ognl上下文物件
OgnlContext context = new OgnlContext();
// 放入資料
User user = new User();
user.setId(100);
user.setName("Jack");
// 【往根元素放入資料】
context.setRoot(user);
// 獲取資料(map)
// 先構建一個Ognl表示式, 再解析表示式
Object ognl = Ognl.parseExpression("address.province");
Object value = Ognl.getValue(ognl, context, context.getRoot());
System.out.println(value);
}
複製程式碼
也就是說,JSP頁面中取出資料的時候,它會先構建一個OGNL表示式,再解析表示式
- 如果是CompoundRoot類的資料,表示式不需要帶#號
- 如果不是CompoundRoot類的資料,表示式需要帶#號
例子:
<!-- 頁面: 必須要拿到ValueStack -->
<br/>1. 取根元素的值<br/>
<s:property value="user.id"/>
<s:property value="user.name"/>
<s:property value="user.address"/>
<s:property value="user.address.city"/>
<s:property value="user.address.province"/>
<br/>2. 取非根元素的值<br/>
<s:property value="#request.cn"/>
<s:property value="#session.Session_data"/>
<s:property value="#application.Application_data"/> <br/>
<!-- 自動找request/session/application,找到後立刻返回 -->
<s:property value="#request_data"/>
<s:property value="#attr.Session_data"/>
<s:property value="#attr.Application_data"/> <br/>
<!-- 獲取請求的引數資料 -->
<s:property value="#parameters.userName"/>
<!-- struts的除錯標籤:可以觀測值棧資料 -->
<s:debug></s:debug>
複製程式碼
OGNL對靜態方法的呼叫
/**
* 3.Ognl對 靜態方法呼叫的支援
* @throws Exception
*/
@Test
public void testOgn3() throws Exception {
// 建立一個Ognl上下文物件
OgnlContext context = new OgnlContext();
// Ognl表單式語言,呼叫類的靜態方法
//Object ognl = Ognl.parseExpression("@Math@floor(10.9)");
// 由於Math類在開發中比較常用,所以也可以這樣寫
Object ognl = Ognl.parseExpression("@@floor(10.9)");
Object value = Ognl.getValue(ognl, context, context.getRoot());
System.out.println(value);
}
複製程式碼
OGNL建立集合
<br/>一、.構建 list集合</br>
<s:iterator var="str" value="{'a','b'}">
<s:property value="#str"/>
</s:iterator>
<br/>一、.構建 map集合</br>
<s:iterator var="en" value="#{'cn':'China','usa':'America'}">
<s:property value="#en.key"/>
<s:property value="#en.value"/> <br/>
</s:iterator>
複製程式碼
構建Map集合的時候,需要使用#號
#OGNL 幾個特殊的符號#
#獲取非根元素值 、 動態都建map集合 $ 在配置檔案取值 % 提供一個ognl表示式執行環境
<body>
<br/>獲取request域資料<br/>
<!-- property 標籤是物件型別的標籤,預設支援ognl表示式, 會從根元素去China名稱對應的值 -->
<s:property value="China"/> <br/>
<!-- 如果直接賦值,需要用單引號 -->
<s:property value="'China'"/> <br/>
<s:property value="%{#request.cn}"/> <br/>
<!-- 值型別的標籤,value值預設就是值型別,不支援ognl表示式 -->
國家:<s:textfield name="txtCountry" value="%{#request.cn}"></s:textfield>
</body>
複製程式碼
如果您覺得這篇文章幫助到了您,可以給作者一點鼓勵