struts2中OGNL詳解

首先了解下OGNL的概念

OGNL是Object-Graph Navigation Language的縮寫,全稱爲對象圖導航語言,是一種功能強大的表達式語言,它經過簡單一致的語法,能夠任意存取對象的屬性或者調用對象的方法,可以遍歷整個對象的結構圖,實現對象屬性類型的轉換等功能。html

此外,還得先需弄懂OGNL的一些知識:

 

1.OGNL表達式的計算是圍繞OGNL上下文進行的。
OGNL上下文實際上就是一個Map對象,由ognl.OgnlContext類表示。它裏面能夠存放不少個JavaBean對象。它有一個上下文根對象。
上下文中的根對象能夠直接使用名來訪問或直接使用它的屬性名訪問它的屬性值。不然要加前綴「#key」。


 

 

 

2.Struts2的標籤庫都是使用OGNL表達式來訪問ActionContext中的對象數據的。如:<s:propertyvalue="xxx"/>。


 

 

 

3.Struts2將ActionContext設置爲OGNL上下文,並將值棧做爲OGNL的根對象放置到ActionContext中。


 

 

 

4.值棧(ValueStack) :
能夠在值棧中放入、刪除、查詢對象。訪問值棧中的對象不用「#」。
Struts2老是把當前Action實例放置在棧頂。因此在OGNL中引用Action中的屬性也能夠省略「#」。
 
5.調用ActionContext的put(key,value)放入的數據,須要使用#訪問。

OGNL中重要的3個符號:#、%、$:

#、%和$符號在OGNL表達式中常常出現,而這三種符號也是開發者不容易掌握和理解的部分,須要時間的積累才漸漸弄清楚……
1.#符號

#符號的用途通常有三種。java

— 訪問非根對象屬性,例如#session.msg表達式,因爲Struts 2中值棧被視爲根對象,因此訪問其餘非根對象時,須要加#前綴。實際上,#至關於ActionContext. getContext();#session.msg表達式至關於ActionContext.getContext().getSession(). getAttribute("msg") 。spring

— 用於過濾和投影(projecting)集合,如persons.{?#this.age>25},persons.{?#this.name=='pla1'}.{age}[0]。apache

— 用來構造Map,例如示例中的#{'foo1':'bar1', 'foo2':'bar2'}。數組

2.%符號

%符號的用途是在標誌的屬性爲字符串類型時,計算OGNL表達式的值,這個相似js中的eval,很暴力。

3.$符號

$符號主要有兩個方面的用途。session

— 在國際化資源文件中,引用OGNL表達式,例如國際化資源文件中的代碼:reg.agerange=國際化資源信息:年齡必須在${min}同${max}之間。app

— 在Struts 2框架的配置文件中引用OGNL表達式,例如:框架

 

  1. <validators>
  2. <field name="intb">
  3. <field-validator type="int">
  4. <param name="min">10</param>
  5. <param name="max">100</param>
  6. <message>BAction-test校驗:數字必須爲${min}爲${max}之間!</message>
  7. </field-validator>
  8. </field>
  9. </validators>

 

下面經過代碼對OGNL有更深的瞭解:

action類OgnlAction.java:
  1. package com.tjcyjd.test.action;
  2.  
  3. import java.util.Date;
  4. import java.util.LinkedList;
  5. import java.util.List;
  6.  
  7. import javax.servlet.http.HttpServletRequest;
  8.  
  9. import org.apache.struts2.ServletActionContext;
  10. import org.apache.struts2.convention.annotation.Action;
  11. import org.apache.struts2.convention.annotation.Namespace;
  12. import org.apache.struts2.convention.annotation.ParentPackage;
  13. import org.apache.struts2.convention.annotation.Result;
  14. import org.apache.struts2.convention.annotation.Results;
  15. import org.springframework.stereotype.Controller;
  16.  
  17. import com.opensymphony.xwork2.ActionContext;
  18. import com.opensymphony.xwork2.ActionSupport;
  19.  
  20. @Controller
  21. @Namespace("/test")
  22. @ParentPackage("struts-default")
  23. @Results( { @Result(name = "success", location = "/other_test/showognl.jsp"),
  24. @Result(name = "fail", location = "/bbs/admin_login.jsp"),
  25. @Result(name = "input", location = "/bbs/admin_login.jsp") })
  26. public class OgnlAction extends ActionSupport {
  27. private static final long serialVersionUID = -1494290883433357310L;
  28. private List<Person> persons;
  29.  
  30. @Action("ognlTest")
  31. public String ognlTest() throws Exception {
  32. // 得到ActionContext實例,以便訪問Servlet API
  33. ActionContext ctx = ActionContext.getContext();
  34. // 存入application
  35. ctx.getApplication().put("msg", "application信息");
  36. // 保存session
  37. ctx.getSession().put("msg", "seesion信息");
  38. // 保存request信息
  39. HttpServletRequest request = ServletActionContext.getRequest();
  40. request.setAttribute("msg", "request信息");
  41. // 爲persons賦值
  42. persons = new LinkedList<Person>();
  43. Person person1 = new Person();
  44. person1.setName("pla1");
  45. person1.setAge(26);
  46. person1.setBirthday(new Date());
  47. persons.add(person1);
  48.  
  49. Person person2 = new Person();
  50. person2.setName("pla2");
  51. person2.setAge(36);
  52. person2.setBirthday(new Date());
  53. persons.add(person2);
  54.  
  55. Person person3 = new Person();
  56. person3.setName("pla3");
  57. person3.setAge(16);
  58. person3.setBirthday(new Date());
  59. persons.add(person3);
  60.  
  61. return SUCCESS;
  62.  
  63. }
  64.  
  65. public List<Person> getPersons() {
  66. return persons;
  67. }
  68.  
  69. public void setPersons(List<Person> persons) {
  70. this.persons = persons;
  71. }
  72. }

jsp頁面showognl.jsp:
  1. <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
  2.  
  3. <%@ taglib prefix="s" uri="/struts-tags" %>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/ xhtml1/DTD/xhtml1-transitional.dtd">
  5.  
  6. <html xmlns="http://www.w3.org/1999/xhtml">
  7.  
  8. <head>
  9.  
  10. <title>Struts2 OGNL 演示</title>
  11.  
  12. </head>
  13.  
  14. <body>
  15.  
  16. <h3>訪問OGNL上下文和Action上下文</h3>
  17.  
  18. <!-使用OGNL訪問屬性值-->
  19.  
  20. <p>parameters: <s:property value="#parameters.msg" /></p>
  21.  
  22. <p>request.msg: <s:property value="#request.msg" /></p>
  23.  
  24. <p>session.msg: <s:property value="#session.msg" /></p>
  25.  
  26. <p>application.msg: <s:property value="#application.msg" /></p>
  27.  
  28. <p>attr.msg: <s:property value="#attr.msg" /></p>
  29.  
  30. <hr />
  31.  
  32. <h3>用於過濾和投影(projecting)集合</h3>
  33.  
  34. <p>年齡大於20</p>
  35.  
  36. <ul>
  37.  
  38. <!-判斷年齡-->
  39.  
  40. <s:iterator value="persons.{?#this.age>20}">
  41.  
  42. <li><s:property value="name" /> - 年齡:<s:property value="age" /></li>
  43.  
  44. </s:iterator>
  45.  
  46. </ul>
  47.  
  48. <p>姓名爲pla1的年齡: <s:property value="persons.{?#this.name=='pla1'}.{age}[0]"/></p>
  49.  
  50. <hr />
  51.  
  52. <h3>構造Map</h3>
  53.  
  54. <s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />
  55.  
  56. <p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>
  57.  
  58. <hr />
  59.  
  60. <h4>%符號的用法</h4>
  61.  
  62. <s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />
  63.  
  64. <p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>
  65.  
  66. <p>不使用%:<s:url value="#foobar['foo1']" /></p>
  67.  
  68. <p>使用%:<s:url value="%{#foobar['foo1']}" /></p>
  69.  
  70. <hr />
  71. <%
  72. request.setAttribute("req", "request scope");
  73. request.getSession().setAttribute("sess", "session scope");
  74. request.getSession().getServletContext().setAttribute("app",
  75. "aplication scope");
  76. %>
  77. 1.經過ognl表達式獲取 屬性範圍中的值
  78. <br>
  79. <s:property value="#request.req" />
  80. <br />
  81. <s:property value="#session.sess" />
  82. <br />
  83. <s:property value="#application.app" />
  84. <br />
  85. <hr>
  86.  
  87. 2.經過<span style="background-color: #fafafa;">ognl表達式建立list 集合 ,而且遍歷出集合中的值
  88. <br>
  89. <s:set name="list" value="{'eeeee','ddddd','ccccc','bbbbb','aaaaa'}"></s:set>
  90. <s:iterator value="#list" var="o">
  91. <!-- ${o }<br/> -->
  92. <s:property />
  93. <br />
  94. </s:iterator>
  95. <br />
  96. <hr>
  97.  
  98. 3.經過ognl表達式建立Map 集合 ,而且遍歷出集合中的值
  99. <br>
  100. <s:set name="map"
  101. value="#{'1':'eeeee','2':'ddddd','3':'ccccc','4':'bbbbb','5':'aaaaa'}"></s:set>
  102. <s:iterator value="#map" var="o">
  103. <!-- ${o.key }->${o.value }<br/> -->
  104. <!-- <s:property value="#o.key"/>-><s:property value="#o.value"/><br/> -->
  105. <s:property value="key" />-><s:property value="value" />
  106. <br />
  107. </s:iterator>
  108. <br />
  109. <hr>
  110. 4.經過ognl表達式 進行邏輯判斷
  111. <br>
  112. <s:if test="'aa' in {'aaa','bbb'}">
  113. aa 在 集合{'aaa','bbb'}中;
  114. </s:if>
  115. <s:else>
  116. aa 不在 集合{'aaa','bbb'}中;
  117. </s:else>
  118. <br />
  119. <s:if test="#request.req not in #list">
  120. 不 在 集合list中;
  121. </s:if>
  122. <s:else>
  123. 在 集合list中;
  124. </s:else>
  125. <br />
  126. <hr>
  127.  
  128. 5.經過ognl表達式 的投影功能進行數據篩選
  129. <br>
  130. <s:set name="list1" value="{1,2,3,4,5}"></s:set>
  131. <s:iterator value="#list1.{?#this>2}" var="o">
  132. <!-- #list.{?#this>2}:在list1集合迭代的時候,從中篩選出當前迭代對象>2的集合進行顯示 -->
  133. ${o }<br />
  134. </s:iterator>
  135. <br />
  136. <hr>
  137. 6.經過ognl表達式 訪問某個類的靜態方法和值
  138. <br>
  139. <s:property value="@java.lang.Math@floor(32.56)" />
  140.  
  141. <s:property value="@com.rao.struts2.action.OGNL1Action@aa" />
  142. <br />
  143. <br />
  144. <hr>
  145. 7.ognl表達式 迭代標籤 詳細
  146. <br>
  147. <s:set name="list2"
  148. value="{'aa','bb','cc','dd','ee','ff','gg','hh','ii','jj'}"></s:set>
  149. <table border="1">
  150. <tr>
  151. <td>索引 </td>
  152. <td></td>
  153. <td>奇?</td>
  154. <td> 偶?</td>
  155. <td>首?</td>
  156. <td> 尾?</td>
  157. <td>當前迭代數量</td>
  158. </tr>
  159. <s:iterator value="#list2" var="o" status="s">
  160. <tr bgcolor="<s:if test="#s.even">pink</s:if>">
  161. <td>
  162. <s:property value="#s.getIndex()" />
  163. </td>
  164. <td>
  165. <s:property />
  166. </td>
  167. <td>
  168. <s:if test="#s.odd">Y</s:if>
  169. <s:else>N</s:else>
  170. </td>
  171. <td>
  172. <s:if test="#s.even">Y</s:if>
  173. <s:else>N</s:else>
  174. </td>
  175. <td>
  176. <s:if test="#s.first">Y</s:if>
  177. <s:else>N</s:else>
  178. </td>
  179. <td>
  180. <s:if test="#s.isLast()">Y</s:if>
  181. <s:else>N</s:else>
  182. </td>
  183. <td>
  184. <s:property value="#s.getCount()"/>
  185. </td>
  186. </tr>
  187. </s:iterator>
  188. </table>
  189. <br>
  190. <hr>
  191.  
  192.  
  193. 8.ognl表達式: if/else if/else 詳細<br>
  194. <% request.setAttribute("aa",0); %>
  195. <s:if test="#request.aa>=0 && #request.aa<=4">
  196. 在0-4之間;
  197. </s:if>
  198. <s:elseif test="#request.aa>=4 && #request.aa<=8">
  199. 在4-8之間;
  200. </s:elseif>
  201. <s:else>
  202. 大於8;
  203. </s:else>
  204. <br>
  205. <hr>
  206. 9.ognl表達式: url 詳細<br>
  207. <% request.setAttribute("aa","sss"); %>
  208. <s:url action="testAction" namespace="/aa/bb">
  209. <s:param name="aa" value="#request.aa"></s:param>
  210. <s:param name="id">100</s:param>
  211. </s:url>
  212. <br/>
  213. <s:set name="myurl" value="'http://www.baidu.com'"></s:set>
  214. value以字符處理: <s:url value="#myurl"></s:url><br>
  215. value明確指定以ognl表達式處理: <s:url value="%{#myurl}"></s:url>
  216. <br>
  217. <hr>
  218. 10.ognl表達式: checkboxlist 詳細<br>
  219. 1> .list 生成;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
  220. name:checkboxlist的名字<br>
  221. list:checkboxlist要顯示的列表<br>
  222. value:checkboxlist默認被選中的選項,checkedchecked=checked<br>
  223. <s:checkboxlist name="checkbox1" list="{'上網','看書','登山','游泳','唱歌'}" value="{'上網','看書'}" ></s:checkboxlist>
  224. <br>
  225. 以上生成代碼:<br>
  226. <xmp>
  227. <input type="checkbox" name="checkbox1" value="上網" id="checkbox1-1" checked="checked"/>
  228. <label for="checkbox1-1" class="checkboxLabel">上網</label>
  229. <input type="checkbox" name="checkbox1" value="看書" id="checkbox1-2" checked="checked"/>
  230. <label for="checkbox1-2" class="checkboxLabel">看書</label>
  231. <input type="checkbox" name="checkbox1" value="登山" id="checkbox1-3"/>
  232. <label for="checkbox1-3" class="checkboxLabel">登山</label>
  233. <input type="checkbox" name="checkbox1" value="游泳" id="checkbox1-4"/>
  234. <label for="checkbox1-4" class="checkboxLabel">游泳</label>
  235. <input type="checkbox" name="checkbox1" value="唱歌" id="checkbox1-5"/>
  236. <label for="checkbox1-5" class="checkboxLabel">唱歌</label>"
  237. </xmp>
  238. 2> .Map 生成;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
  239. name:checkboxlist的名字<br>
  240. list:checkboxlist要顯示的列表<br>
  241. listKey:checkbox 的value的值<br>
  242. listValue:checkbox 的lablel(顯示的值)<br>
  243. value:checkboxlist默認被選中的選項,checkedchecked=checked<br>
  244. <s:checkboxlist name="checkbox2" list="#{1:'上網',2:'看書',3:'登山',4:'游泳',5:'唱歌'}" listKey="key" listValue="value" value="{1,2,5}" ></s:checkboxlist>
  245. <br>
  246. 以上生成代碼:<br>
  247. <xmp>
  248. <input type="checkbox" name="checkbox2" value="1" id="checkbox2-1" checked="checked"/>
  249. <label for="checkbox2-1" class="checkboxLabel">上網</label>
  250. <input type="checkbox" name="checkbox2" value="2" id="checkbox2-2" checked="checked"/>
  251. <label for="checkbox2-2" class="checkboxLabel">看書</label>
  252. <input type="checkbox" name="checkbox2" value="3" id="checkbox2-3"/>
  253. <label for="checkbox2-3" class="checkboxLabel">登山</label>
  254. <input type="checkbox" name="checkbox2" value="4" id="checkbox2-4"/>
  255. <label for="checkbox2-4" class="checkboxLabel">游泳</label>
  256. <input type="checkbox" name="checkbox2" value="5" id="checkbox2-5" checked="checked"/>
  257. <label for="checkbox2-5" class="checkboxLabel">唱歌</label>
  258. </xmp>
  259. <hr>
  260. </body>
  261. </html>

總結OGNL的使用方法:jsp

訪問屬性

名字屬性獲取:<s:property value="user.username"/><br>ide

地址屬性獲取:<s:property value="user.address.addr"/><br>

訪問方法

調用值棧中對象的普通方法:<s:property value="user.get()"/><br>

訪問靜態屬性和方法

調用Action中的靜態方法:<s:property value="@struts.action.LoginAction@get()"/>

調用JDK中的類的靜態方法:<s:property value="@java.lang.Math@floor(44.56)"/><br>

調用JDK中的類的靜態方法(同上):<s:property value="@@floor(44.56)"/><br>

調用JDK中的類的靜態方法:<s:property value="@java.util.Calendar@getInstance()"/><br>

調用普通類中的靜態屬性:<s:property value="@struts.vo.Address@TIPS"/><br>

訪問構造方法

調用普通類的構造方法:<s:property value="new struts.vo.Student('李曉紅' , '美女' , 3 , 25).username"/>

 

1.5. 訪問數組

獲取List:<s:property value="testList"/><br>

獲取List中的某一個元素(可使用相似於數組中的下標獲取List中的內容):

<s:property value="testList[0]"/><br>

獲取Set:<s:property value="testSet"/><br>

獲取Set中的某一個元素(Set因爲沒有順序,因此不能使用下標獲取數據):

<s:property value="testSet[0]"/><br> ×

獲取Map:<s:property value="testMap"/><br>

獲取Map中全部的鍵:<s:property value="testMap.keys"/><br>

獲取Map中全部的值:<s:property value="testMap.values"/><br>

獲取Map中的某一個元素(可使用相似於數組中的下標獲取List中的內容):

<s:property value="testMap['m1']"/><br>

獲取List的大小:<s:property value="testSet.size"/><br>

 

訪問集合 – 投影、選擇(? ^ $)

利用選擇獲取List中成績及格的對象:<s:property value="stus.{?#this.grade>=60}"/><br>

利用選擇獲取List中成績及格的對象的username:

<s:property value="stus.{?#this.grade>=60}.{username}"/><br>

利用選擇獲取List中成績及格的第一個對象的username:

<s:property value="stus.{?#this.grade>=60}.{username}[0]"/><br>

利用選擇獲取List中成績及格的第一個對象的username:

<s:property value="stus.{^#this.grade>=60}.{username}"/><br>

利用選擇獲取List中成績及格的最後一個對象的username:

<s:property value="stus.{$#this.grade>=60}.{username}"/><br>

利用選擇獲取List中成績及格的第一個對象而後求大小:

<s:property value="stus.{^#this.grade>=600}.{username}.size"/><br>

集合的僞屬性

OGNL可以引用集合的一些特殊的屬性,這些屬性並非JavaBeans模式,例如size(),length()等等. 當表達式引用這些屬性時,OGNL會調用相應的方法,這就是僞屬性.

集合

僞屬性

Collection(inherited by Map, List & Set)

size ,isEmpty

List

iterator

Map

keys , values

Set

iterator

Iterator

next , hasNext

Enumeration

next , hasNext , nextElement , hasMoreElements

 

Lambda :[…]

格式::[…]

使用Lambda表達式計算階乘:

<s:property value="#f = :[#this==1?1:#this*#f(#this-1)] , #f(4)"/><br>

OGNL中#的使用

#能夠取出堆棧上下文中的存放的對象.

名稱

做用

例子

parameters

包含當前HTTP請求參數的Map

#parameters.id[0]做用至關於

request.getParameter("id")

request

包含當前HttpServletRequest的屬性(attribute)的Map

#request.userName至關於

request.getAttribute("userName")

session

包含當前HttpSession的屬性(attribute)的Map

#session.userName至關於

session.getAttribute("userName")

application

包含當前應用的ServletContext的屬性(attribute)的Map

#application.userName至關於

application.getAttribute("userName")

attr

用於按request > session > application順序訪問其屬性(attribute)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

獲取Paraments對象的屬性:<s:property value="#parameters.username"/>

OGNL中%的使用

用%{}能夠取出存在值堆棧中的Action對象,直接調用它的方法.

例如你的Action若是繼承了ActionSupport .那麼在頁面標籤中,用%{getText('key')}的方式能夠拿出國際化信息.

OGNL中$的使用

「$」有兩個主要的用途

l 用於在國際化資源文件中,引用OGNL表達式

l 在Struts 2配置文件中,引用OGNL表達式

值棧

ValueStack對象。這個對象貫穿整個Action的生命週期(每一個Action類的對象實例會擁有一個ValueStack對象)。當 Struts 2接收到一個.action的請求後,會先創建Action類的對象實例,但並不會調用Action方法,而是先將Action類的相應屬性放到 ValueStack對象的頂層節點(ValueStack對象至關於一個棧)。

在Action中得到ValueStack對象:ActionContext.getContext().getValueStack()

l Top語法

使用Top獲取值棧中的第二個對象:<s:property value="[1].top.對象"/>

l N語法

使用N獲取值棧中的第二個對象:<s:property value="[1].對象"/>

l @語法

調用action中的靜態方法:<s:property value="@vs1@靜態方法"/> vs:值棧 1:表示第一個。

相關文章
相關標籤/搜索