OGNL是Object Graphic Navigation Language 是操做對象屬性的開源表達式。 Struts2框架使用OGNL做爲默認的表達式語言。java
在學習JSP的時候,咱們已經學習過了EL表達式。EL表達式用起來也十分簡單…咱們在Struts2框架中也是可使用EL表達式的…那麼OGNL表達式好在哪裏呢??markdown
OGNL是Struts2的默認表達式語言,OGNL是配搭Strut2的標籤使用的..咱們學習了OGNL表達式,就能夠更好地理解Struts2標籤的運行以及Struts2內部的存儲結構.session
在講解OGNL表達式以前,咱們先來看看valueStack對象…valueStack是Struts2數據存儲的核心…咱們首先要知道數據是怎麼存的,存到哪裏,而後纔講解OGNL表達式是怎麼取出數據的。app
valueStack也被稱做值棧對象..框架
//獲取值棧對象的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結構..spa
爲了讓request、response等域對象能夠存儲多個值,值也是使用Map結構…debug
public class OgnlContext implements Map {}
CompoundRoot保存着這樣的數據:代理
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集合的時候,須要使用#號
#獲取非根元素值 、 動態都建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>