OGNL是Object Graphic Navigation Language 是操做對象屬性的開源表達式。 Struts2框架使用OGNL做爲默認的表達式語言。html
在學習JSP的時候,咱們已經學習過了EL表達式。EL表達式用起來也十分簡單...咱們在Struts2框架中也是可使用EL表達式的...那麼OGNL表達式好在哪裏呢??java
OGNL是Struts2的默認表達式語言,OGNL是配搭Strut2的標籤使用的..咱們學習了OGNL表達式,就能夠更好地理解Struts2標籤的運行以及Struts2內部的存儲結構.微信
在講解OGNL表達式以前,咱們先來看看valueStack對象...valueStack是Struts2數據存儲的核心...咱們首先要知道數據是怎麼存的,存到哪裏,而後纔講解OGNL表達式是怎麼取出數據的。session
valueStack也被稱做值棧對象..app
//獲取值棧對象的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
}
複製代碼
上面已經說了,用戶訪問Action時,會建立Action對象,valueStack對象。Struts2內部會將Action對象存到valueStack對象之中...那麼valueStack的存儲結構是什麼樣的呢???咱們來看看框架
Action對象和Action的成員屬性等值都是存到CompoundRoot下的.該CompoundRoot繼承着ArrayList,所以它是List結構的學習
public class CompoundRoot extends ArrayList {}
複製代碼
OgnlContext對象存儲着相關的域對象:request、response、session等數據,實現Map集合,是Map結構..編碼
爲了讓request、response等域對象能夠存儲多個值,值也是使用Map結構...spa
public class OgnlContext implements Map {}
複製代碼
CompoundRoot保存着這樣的數據:debug
OgnlContext保存着這樣的數據:
也就是說經過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表達式,再解析表達式
<!-- 頁面: 必需要拿到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>
複製代碼
/** * 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);
}
複製代碼
<br/>1、.構建 list集合</br>
<s:iterator var="str" value="{'a','b'}">
<s:property value="#str"/>
</s:iterator>
<br/>1、.構建 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>
複製代碼
若是文章有錯的地方歡迎指正,你們互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠關注微信公衆號:Java3y