基礎(chǔ)知識(shí)(三) Struts2中的OGNL表達(dá)式 淺析值棧 ValueStack對(duì)象相當(dāng)于一個(gè)棧,它貫穿整個(gè)Action的生命周期,每個(gè)Action類的對(duì)象實(shí)例都會(huì)擁有一個(gè)ValueStack對(duì)象 當(dāng)Struts2接收到一個(gè)*.action請(qǐng)求后,并不是直接調(diào)用Action方法,而是先將Action類的相應(yīng)屬性放到ValueStack對(duì)象的頂層節(jié)點(diǎn) 值棧也位于內(nèi)存中,它也是和parameters、request、session、application、attr對(duì)象放在一起的 值棧屬于ONGL Context里面的根對(duì)象。也就是說(shuō)它位于整個(gè)內(nèi)存中最最重要的地方,所以叫根對(duì)象 根對(duì)象和另外五個(gè)對(duì)象是有區(qū)別的,根對(duì)象可以省寫#號(hào),比如<s:property value="user.username"/> 值棧的生命周期與request請(qǐng)求相關(guān),每次請(qǐng)求產(chǎn)生一個(gè)值棧。默認(rèn)所有的Action會(huì)被自動(dòng)放到值棧里 服務(wù)器跳轉(zhuǎn)時(shí)共用值棧 假設(shè)從一個(gè)Action11通過(guò)服務(wù)器跳轉(zhuǎn)到Action22的話,就意味著這兩個(gè)Action是共享一個(gè)值棧的,因?yàn)橐淮握?qǐng)求只使用一個(gè)值棧 這時(shí)內(nèi)存中情況是這樣的:首先接收到Action11請(qǐng)求后,會(huì)產(chǎn)生一個(gè)值棧,在棧頂存放Action11對(duì)象以及它所有的屬性 然后經(jīng)過(guò)服務(wù)器跳轉(zhuǎn)到Action22,這時(shí)就會(huì)把Action22對(duì)象壓入值棧的棧頂位置,此時(shí)Action11對(duì)象以及它的所有屬性就位于棧底了 取值過(guò)程 棧的特征是后進(jìn)先出。于是首先到棧頂?shù)膶?duì)象里查找是否存在這個(gè)屬性,如果棧頂?shù)腁ction22對(duì)象中不存在這個(gè)屬性的話 它就會(huì)繼續(xù)向下尋找直至棧底對(duì)象,一直查找是否存在這個(gè)屬性 如果最后找到該屬性的話,那么就會(huì)在JSP頁(yè)面中通過(guò)<s:property value="username"/>輸出屬性值 如果在Action22和Action11都有一個(gè)同名的同類型的username屬性的話,那么將輸出Action22中的屬性值 因?yàn)樗窍葟臈m旈_始尋找屬性的,值棧的特征就是后進(jìn)先出,但有個(gè)前提:請(qǐng)求過(guò)程是通過(guò)服務(wù)器跳轉(zhuǎn)的 三個(gè)語(yǔ)法 假設(shè)此時(shí)想要獲取Action11中的username屬性的話,就可以使用值棧的Top語(yǔ)法或者N語(yǔ)法 使用Top語(yǔ)法獲取值棧中的第二個(gè)對(duì)象的屬性:<s:property value="[1].top.username"/> 使用 N 語(yǔ)法獲取值棧中的第二個(gè)對(duì)象的屬性:<s:property value="[1].username"/> 另外值棧還有一個(gè)@語(yǔ)法,例如使用@語(yǔ)法調(diào)用Action中的靜態(tài)方法:<s:property value="@vs@getVOMethod()"/> @vs@get()等價(jià)于@vs1@getVOMethod(),指的是棧頂對(duì)象的靜態(tài)getVOMethod()方法 同理@vs2@getVOMethod()就是取值棧中第二個(gè)對(duì)象的靜態(tài)getVOMethod()方法 客戶端跳轉(zhuǎn)時(shí)使用各自的值棧 假如中間某一個(gè)步驟中出現(xiàn)了客戶端跳轉(zhuǎn)的話,那么兩個(gè)Action所使用的就是兩個(gè)不同的值棧了 所以在Action22中就不能再使用Action11中的屬性了,在最后跳轉(zhuǎn)到的JSP頁(yè)面中也就無(wú)法獲取Action11的屬性了 也即從Action22跳轉(zhuǎn)到JSP頁(yè)面時(shí)使用的是redirect的話,那么最后值棧中是沒(méi)有任何的Action對(duì)象的 這個(gè)時(shí)候我們可以通過(guò)鏈接傳參,比如<result type="redirect">test.jsp?netname=${username}</result> 意思就是取出Action22中的username屬性作為參數(shù),通過(guò)瀏覽器地址欄傳遞到JSP頁(yè)面中 然后使用OGNL中的#號(hào)獲取Paraments對(duì)象的屬性,即<s:property value="#parameters.netname"/>就可以取到值了 輔助參考:http://blog.csdn.net/jadyer/archive/2010/09/16/5887509.aspx 手工向值棧中壓入對(duì)象 正常情況下值棧保存的是Action對(duì)象,而我們也可以直接往值棧中添加其它對(duì)象,這時(shí)可以在Action中添加如下代碼 向值棧中添加對(duì)象:ActionContext.getContext.getValueStack().push(new Student("沈浪",22)); 而且我們手工往值棧中添加的Student對(duì)象會(huì)位于棧頂。這是因?yàn)镾truts2會(huì)首先初始化Action,然后才能調(diào)用它的方法 初始化Action的時(shí)候,便把Action放到值棧中了,然后在執(zhí)行它的execute()方法時(shí),就又往值棧中添加了Student對(duì)象 淺析OGNL OGNL是Object-Graph Navigation Language的縮寫,是一種功能強(qiáng)大的表達(dá)式語(yǔ)言 通過(guò)它簡(jiǎn)單一致的表達(dá)式語(yǔ)法,可以存取對(duì)象的任意屬性,調(diào)用對(duì)象的方法,遍歷整個(gè)對(duì)象的結(jié)構(gòu)圖,實(shí)現(xiàn)字段類型轉(zhuǎn)化等功能 OGNL用得最多的地方就是和Struts2的標(biāo)簽綁定,也可以在配置文件中通過(guò)${}使用OGNL表達(dá)式 OGNL中$號(hào)的使用 1..在國(guó)際化資源文件中,引用OGNL表達(dá)式 2..在struts.xml文件中,引用OGNL表達(dá)式 OGNL中%號(hào)的使用 1..使用%{}可以取出保存在值堆棧中的Action對(duì)象,直接調(diào)用它的方法 2..如果Action繼承了ActionSupport,那么在頁(yè)面標(biāo)簽中可以使用%{getText('key')}獲取國(guó)際化信息 輔助參考:http://blog.csdn.net/jadyer/archive/2010/09/16/5887545.aspx OGNL中#號(hào)的使用 OGNL中的#號(hào)可以取出堆棧上下文中存放的對(duì)象 | 名稱 | 作用 | 例子 | | attr | 用于按request>>session>>application順序訪問(wèn)其屬性 | #attr.userName相當(dāng)于按順序從三個(gè)范圍讀取userName屬性直到找到為止 | | request | 包含當(dāng)前HttpServletRequest的屬性的Map | #request.userName相當(dāng)于request.getAttribute("userName") | | session | 包含當(dāng)前HttpSession的屬性的Map | #session.userName相當(dāng)于session.getAttribute("userName") | | application | 包含當(dāng)前應(yīng)用的ServletContext的屬性的Map | #application.userName相當(dāng)于application.getAttribute("userName") | | parameters | 包含當(dāng)前HTTP請(qǐng)求參數(shù)的Map | #parameters.id[0]相當(dāng)于request.getParameter("id") | 獲取Action中的屬性值或者Action中的對(duì)象的某某屬性值 利用<s:property/>標(biāo)簽可以直接獲取Action中的引用類型user里面的username屬性 同樣可以通過(guò)user.address.addr獲取user中引用類型address中的addr屬性的值 像這種一層一層往下傳遞的訪問(wèn)方式,即所謂的導(dǎo)航,也就是一步步的往下調(diào)用 調(diào)用Action的對(duì)象里面的普通方法 默認(rèn)的會(huì)把Action放到值棧里面,而值棧在訪問(wèn)的時(shí)候,并不需要值棧的名字 當(dāng)我們調(diào)用<s:property value="user.getVOMethod()"/>的時(shí)候 它會(huì)自動(dòng)到值棧里面查找Action對(duì)象里面有沒(méi)有user對(duì)象,然后它就發(fā)現(xiàn)有user 然后它就再找user里面有沒(méi)有g(shù)etVOMethod()方法,然后它發(fā)現(xiàn)有,于是調(diào)用getVOMethod() 實(shí)際上調(diào)用User中的getVOMethod()方法的過(guò)程與獲取表單中的姓名密碼的方式都是相同的 都是到值棧里面查找,找是否存在user對(duì)象,如果存在,接著查找user中是否存在某某屬性或方法 調(diào)用Action中的靜態(tài)方法 同樣我們也可以在JSP頁(yè)面中寫一個(gè)OGNL表達(dá)式調(diào)用Action中的靜態(tài)方法 調(diào)用Action中的靜態(tài)方法時(shí),與調(diào)用user對(duì)象的getVOMethod()方法的過(guò)程,是截然不同的 此時(shí)value的寫法是固定的,以@開頭,后面跟上具體的包名,然后@加上靜態(tài)方法 比如<s:property value="@com.jadyer.action.LoginAction@getStatic()"/> 另外user對(duì)象是LoginAction中的一個(gè)屬性,這個(gè)屬性會(huì)自動(dòng)的放到值棧里面 而值棧調(diào)用的時(shí)候,不用加上@或者包名等等,所以直接user.getVOMethod()就可以了 調(diào)用JDK類中的靜態(tài)方法 可以使用<s:property value="@@floor(46.58)"/>輸出floor()的執(zhí)行結(jié)果 這就意味著如果不在@@中指定類的話,默認(rèn)的就表示java.lang.Math類 當(dāng)前大多數(shù)情況下,我們都不會(huì)省略這個(gè)類,都會(huì)寫全了的,然后在后面加上靜態(tài)方法 集合的偽屬性 OGNL能夠引用集合的一些特殊的屬性,這些屬性并不是JavaBean模式,例如size()、length() 當(dāng)表達(dá)式引用這些屬性時(shí),OGNL會(huì)調(diào)用相應(yīng)的方法,這就是偽屬性 比如獲取List的大小:<s:property value="testList.size"/> ??????List的偽屬性:size、isEmpty、iterator ???????Set的偽屬性:size、isEmpty、iterator ???????Map的偽屬性:size、isEmpty、keys、values ??Iterator的偽屬性:next、hasNext Enumeration偽屬性:next、hasNext、nextElement、hasMoreElements 獲取集合中元素的實(shí)質(zhì)就是調(diào)用它的toString()方法 它還可以直接獲取集合中的元素,事實(shí)上是在調(diào)用集合的toString()方法 所以我們可以根據(jù)實(shí)際情況通過(guò)重寫集合的toString()方法來(lái)實(shí)現(xiàn)個(gè)性? 化輸出 甚至它還可以像訪問(wèn)數(shù)組那樣,直接testList[2]獲取集合中的元素 但這種方法只適用于List,不適用于Map。因?yàn)镸ap的索引是key,不是數(shù)值 另外,由于HashSet中的元素是沒(méi)有順序的,所以也不能用下標(biāo)獲取單個(gè)元素 Lambda表達(dá)式 補(bǔ)充一下:使用Lambda表達(dá)式可以在OGNL中書寫遞歸式子,在幫助中對(duì)它有很詳細(xì)的說(shuō)明 打開幫助中的//struts-2.0.14-all//struts-2.0.14//docs//index.html頁(yè)面 在左側(cè)的Documentation下面點(diǎn)擊Guides鏈接,然后在這個(gè)頁(yè)面中點(diǎn)擊OGNL 最后跳轉(zhuǎn)到//struts-2.0.14-all//struts-2.0.14//docs//docs//ognl.html 將這個(gè)頁(yè)面右側(cè)的下拉條拖放到最下面,就會(huì)看到它的說(shuō)明了,它舉的例子如下所示 <s:property value="#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" /> Lambda表達(dá)式的語(yǔ)法是:[...]?,中括號(hào)前面有一個(gè)冒號(hào),所有東西都在中括號(hào)里面寫 也就是說(shuō)我們只要看到一個(gè)冒號(hào)跟著一個(gè)中括號(hào),就表示這里使用的是Lambda表達(dá)式 #this指的是表達(dá)式的參數(shù) 所以這個(gè)例子可以這樣理解:先判斷這個(gè)參數(shù)是否等于零,如果等于零,那么它的值最后就是零 如果參數(shù)不等于零,就再判斷它是否等于壹。如果參數(shù)等于壹,那么它的值最后就是壹 如果參數(shù)不等于壹,就繼續(xù)調(diào)用#fib。注意這里已經(jīng)用中括號(hào)將整體的值賦給了fib 實(shí)際上很少能夠用得到Lambda表達(dá)式 利用投影獲取屬性 利用投影獲取List中對(duì)象的username屬性時(shí),其中{}表示的是一個(gè)集合 stus.{username}就表示將suts中所有的username屬性取出組成一個(gè)新的列表 利用選擇獲取屬性 OGNL表達(dá)式是很靈活的,可以同時(shí)使用選擇技術(shù)與投影技術(shù)獲取屬性 使用選擇技術(shù)時(shí),#this代表當(dāng)前元素,問(wèn)號(hào)?是把所有滿足條件的元素都取出來(lái) 上箭頭^是開始的意思,所以stus.{^#this.grade>=60}.{username}輸出的是[張三] 注意,此時(shí)輸出文本中包含中括號(hào),這表示它是一個(gè)列表 而stus.{?#this.grade>=60}.{username}[0]輸出的是張三,是字符串,二者是不同的 美元符號(hào)$是結(jié)束的意思,所以stus.{$#this.grade>=60}.{username}輸出的是[王五] 這三個(gè)符合:問(wèn)號(hào)、上箭頭、美元符所返回的都是List 補(bǔ)充 1..當(dāng)OGNL取不到值的時(shí)候,它不會(huì)報(bào)錯(cuò),而是什么都不顯示 2..<s:property value="[0]"/>返回的是ValueStack中從上至下的所有的Object ????<s:property value="[1]"/>返回的是ValueStack中從上至下的第二個(gè)Object 3..<s:property value="[0].username"/>返回的是成員變量username的值 ??? 假設(shè)ValueStack中存在兩個(gè)Action的話,如果第一個(gè)Action如果沒(méi)有username變量 ??? 那么它會(huì)繼續(xù)找第二個(gè)Action。那么在什么情況下ValueStack中會(huì)存在兩個(gè)Action呢 ??? 答案是在struts.xml中配置的是從一個(gè)Action通過(guò)<result type="chain">跳轉(zhuǎn)到另一個(gè)Action 4..<constant name="struts.ognl.allowStaticMethodAccess" value="true"/> ??? 在Struts2.1.6中必須設(shè)置struts.ognl.allowStaticMethodAccess為true之后 ??? 才允許使用OGNL訪問(wèn)靜態(tài)方法。而在Struts2.0.11則無(wú)需設(shè)置,即可直接訪問(wèn) 下面是OGNL測(cè)試的工程代碼,這是一個(gè)Struts2.0.11應(yīng)用 首先是web.xml文件 [xhtml]?view plaincopy <?xmlversion="1.0"encoding="UTF-8"?>?<web-app?version="2.5"??????xmlns="http://java.sun.com/xml/ns/javaee"??????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"??????xsi:schemaLocation="http://java.sun.com/xml/ns/javaee??;????http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">?????<filter>?????????<filter-name>struts2</filter-name>?????????<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>?????</filter>?????<filter-mapping>?????????<filter-name>struts2</filter-name>?????????<url-pattern>/*</url-pattern>?????</filter-mapping>?????<welcome-file-list>?????????<welcome-file>login.jsp</welcome-file>?????</welcome-file-list>???</web-app>? [xhtml]?view plaincopy <?xml?version="1.0"?encoding="UTF-8"?>??<web-app?version="2.5"???????xmlns="http://java.sun.com/xml/ns/javaee"???????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"???????xsi:schemaLocation="http://java.sun.com/xml/ns/javaee???;????http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">??????<filter>??????????<filter-name>struts2</filter-name>??????????<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>??????</filter>??????<filter-mapping>??????????<filter-name>struts2</filter-name>??????????<url-pattern>/*</url-pattern>??????</filter-mapping>??????<welcome-file-list>??????????<welcome-file>login.jsp</welcome-file>??????</welcome-file-list>????</web-app>?? 然后是用于輸入用戶名和密碼等信息的測(cè)試頁(yè)面login.jsp ? [xhtml]?view plaincopy <%@ page?language="java"pageEncoding="UTF-8"%>?<h1>這是測(cè)試OGNL使用的登錄頁(yè)面</h1>?<h3><fontcolor="red">提示:</font>程序設(shè)定的用戶名和密碼各為<fontcolor="blue"><strong>admin</strong></font>和<fontcolor="blue"><strong>jadyer</strong></font></h3>?<h3><fontcolor="red">注意:</font>用戶名和密碼不正確時(shí)將停留在頁(yè)面不動(dòng)</h3>?<formaction="<%=request.getContextPath()%>/login.action"method="POST">?????<%--這里user.username匹配的是LoginAction中的引用類型user里面的username屬性--%>?????<%--查看標(biāo)簽庫(kù)說(shuō)明的話,就知道name中指定的是對(duì)象。這里它不是字符串,而是OGNL表達(dá)式--%>???? 姓名:<inputtype="text"name="user.username"><br>???? 密碼:<inputtype="text"name="user.password"><br>???? 地址:<inputtype="text"name="user.address.addr"><br>?????<inputtype="submit"value="測(cè)試OGNL的輸出">?</form>? [xhtml]?view plaincopy <%@?page?language="java"?pageEncoding="UTF-8"%>??<h1>這是測(cè)試OGNL使用的登錄頁(yè)面</h1>??<h3><font?color="red">提示:</font>程序設(shè)定的用戶名和密碼各為<font?color="blue"><strong>admin</strong></font>和<font?color="blue"><strong>jadyer</strong></font></h3>??<h3><font?color="red">注意:</font>用戶名和密碼不正確時(shí)將停留在頁(yè)面不動(dòng)</h3>??<form?action="<%=request.getContextPath()%>/login.action"?method="POST">??????<%--這里user.username匹配的是LoginAction中的引用類型user里面的username屬性--%>??????<%--查看標(biāo)簽庫(kù)說(shuō)明的話,就知道name中指定的是對(duì)象。這里它不是字符串,而是OGNL表達(dá)式--%>??????姓名:<input?type="text"?name="user.username"><br>??????密碼:<input?type="text"?name="user.password"><br>??????地址:<input?type="text"?name="user.address.addr"><br>??????<input?type="submit"?value="測(cè)試OGNL的輸出">??</form>?? 然后是用于顯示OGNL處理結(jié)果的loginSuc.jsp頁(yè)面 ? [xhtml]?view plaincopy <%@ page?language="java"pageEncoding="UTF-8"%>?<%@ taglib?prefix="s"uri="/struts-tags"%>?<h1>這是使用OGNL輸出的結(jié)果頁(yè)面</h1>?<table?border="9">?????<tr>?????????<tdalign="right">獲取姓名屬性:</td>?????????<tdalign="left"><s:propertyvalue="user.username"/></td>?????????<%-- 另外還有兩種寫法也是可以正常輸出值棧中對(duì)象的普通屬性的 --%>?????????<%--?<s:propertyvalue="user['username']"/>?--%>?????????<%--?<s:propertyvalue="user[/"username/"]"/>?--%>?????????<%-- 但是如果寫成下面這種形式的話,就什么都不會(huì)輸出了 --%>?????????<%--?<s:propertyvalue="user[username]"/>?--%>?????</tr>?????<tr>?????????<tdalign="right">獲取地址屬性:</td>?????????<tdalign="left"><s:propertyvalue="user.address.addr"/></td>?????</tr>?????<tr>?????????<tdalign="right">調(diào)用值棧中的對(duì)象的普通方法:</td>?????????<tdalign="left"><s:propertyvalue="user.getVOMethod()"/></td>?????</tr>?????<tr>?????????<tdalign="right">調(diào)用值棧中Action的普通方法:</td>?????????<tdalign="left"><s:propertyvalue="getCommon()"/></td>?????</tr>?</table>?<hr/>?<table?border="9">?????<tr>?????????<tdalign="right">獲取普通類的靜態(tài)屬性:</td>?????????<tdalign="left"><s:propertyvalue="@com.jadyer.vo.Address@TIPS"/></td>?????</tr>?????<tr>?????????<tdalign="right">訪問(wèn)普通類的構(gòu)造方法:</td>?????????<tdalign="left"><s:propertyvalue="new com.jadyer.vo.Student('張小三',22).username"/></td>?????</tr>?????<tr>?????????<tdalign="right">調(diào)用Action中的靜態(tài)方法:</td>?????????<tdalign="left"><s:propertyvalue="@com.jadyer.action.LoginAction@getStatic()"/></td>?????</tr>?????<tr>?????????<tdalign="right">調(diào)用JDK中的類的靜態(tài)方法:</td>?????????<tdalign="left"><s:propertyvalue="@java.util.Calendar@getInstance().time"/></td>?????</tr>?????<tr>?????????<tdalign="right">調(diào)用JDK中的類的靜態(tài)方法:</td>?????????<tdalign="left"><s:propertyvalue="@java.lang.Math@floor(46.58)"/></td>?????</tr>?????<tr>?????????<tdalign="right">調(diào)用JDK中的類的靜態(tài)方法:</td>?????????<tdalign="left"><s:propertyvalue="@@floor(46.58)"/></td>?????</tr>?</table>?<hr/>?<tableborder="9">?????<tr>?????????<tdalign="right">獲取List中的所有元素:</td>?????????<tdalign="left"><s:propertyvalue="testList"/></td>?????</tr>?????<tr>?????????<tdalign="right">獲取Set中的所有元素:</td>?????????<tdalign="left"><s:propertyvalue="testSet"/></td>?????</tr>?????<tr>?????????<tdalign="right">獲取Map中的所有元素:</td>?????????<tdalign="left"><s:propertyvalue="testMap"/></td>?????</tr>?????<tr>?????????<tdalign="right">獲取Map中的某個(gè)元素:</td>?????????<tdalign="left"><s:propertyvalue="testMap['m22']"/></td>?????????<%-- 另外還有兩種寫法也是可以正常獲取Map中的某個(gè)具體元素的 --%>?????????<%--?<s:propertyvalue="testMap.m22"/>?--%>?????????<%--?<s:propertyvalue="testMap[/"m22/"]"/>?--%>?????</tr>?????<tr>?????????<tdalign="right">獲取Set中的某個(gè)元素:</td>?????????<%-- 由于Set中的元素是無(wú)順序的,所以不能使用下標(biāo)獲取數(shù)據(jù),所以這里什么也得不到 --%>?????????<tdalign="left"><s:propertyvalue="testSet[2]"/></td>?????</tr>?????<tr>?????????<tdalign="right">獲取List中的某個(gè)元素:</td>?????????<tdalign="left"><s:propertyvalue="testList[2]"/></td>?????</tr>?</table>?<hr/>?<table?border="9">?????<tr>?????????<tdalign="right">獲取List的大小:</td>?????????<tdalign="left"><s:propertyvalue="testList.size"/></td>?????</tr>?????<tr>?????????<tdalign="right">獲取Set的大小:</td>?????????<tdalign="left"><s:propertyvalue="testSet.size"/></td>?????</tr>?????<tr>?????????<tdalign="right">獲取Map的大小:</td>?????????<tdalign="left"><s:propertyvalue="testMap.size"/></td>?????</tr>?????<tr>?????????<tdalign="right">獲取Map中所有的鍵:</td>?????????<tdalign="left"><s:propertyvalue="testMap.keys"/></td>?????</tr>?????<tr>?????????<tdalign="right">獲取Map中所有的值:</td>?????????<tdalign="left"><s:propertyvalue="testMap.values"/></td>?????</tr>?????<tr>?????????<tdalign="right">Lambda計(jì)算4的階乘:</td>?????????<tdalign="left"><s:propertyvalue="#f= :[#this==1?1 : #this*#f(#this-1)],#f(4)"/></td>?????</tr>?</table>?<hr/>?<tableborder="9">?????<tr>?????????<tdalign="right">獲取List中的所有對(duì)象:</td>?????????<tdalign="left"><s:propertyvalue="stus"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用投影獲取List中對(duì)象的名字:</td>?????????<tdalign="left"><s:propertyvalue="stus.{username}"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用投影獲取List中第二個(gè)對(duì)象的名字:</td>?????????<%-- 使用<s:propertyvalue="stus[1].{username}"/>獲取到的值為:[李四] --%>?????????<%-- 二者的區(qū)別在于:后者比前者多了一個(gè)中括號(hào) --%>?????????<tdalign="left">?????????????<s:propertyvalue="stus.{username}[1]"/>???????????????????<s:propertyvalue="stus[1].{username}"/>?????????</td>?????</tr>?????<tr>?????????<tdalign="right">利用選擇獲取List中成績(jī)及格的所有對(duì)象:</td>?????????<tdalign="left"><s:propertyvalue="stus.{?#this.grade>=60}"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用選擇獲取List中成績(jī)及格的第一個(gè)對(duì)象:</td>?????????<tdalign="left"><s:propertyvalue="stus.{^#this.grade>=60}"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用選擇獲取List中成績(jī)及格的最后一個(gè)對(duì)象:</td>?????????<tdalign="left"><s:propertyvalue="stus.{$#this.grade>=60}"/></td>?????</tr>?</table>?<hr/>?<tableborder="9">?????<tr>?????????<tdalign="right">利用選擇獲取List中成績(jī)及格的所有對(duì)象的名字:</td>?????????<tdalign="left"><s:propertyvalue="stus.{?#this.grade>=60}.{username}"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用選擇獲取List中成績(jī)及格的第二個(gè)對(duì)象的名字:</td>?????????<tdalign="left"><s:propertyvalue="stus.{?#this.grade>=60}.{username}[1]"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用選擇獲取List中成績(jī)及格的第一個(gè)對(duì)象的名字:</td>?????????<tdalign="left"><s:propertyvalue="stus.{^#this.grade>=60}.{username}"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用選擇獲取List中成績(jī)及格的最后一個(gè)對(duì)象的名字:</td>?????????<tdalign="left"><s:propertyvalue="stus.{$#this.grade>=60}.{username}"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用選擇獲取List中成績(jī)及格的第一個(gè)對(duì)象然后求大小:</td>?????????<tdalign="left"><s:propertyvalue="stus.{^#this.grade>=60}.{username}.size"/></td>?????</tr>?</table>?<hr/>?<table?border="9">?????<tr>?????????<tdalign="right">利用OGNL中的#號(hào)獲取attr中的屬性:</td>?????????<tdalign="left"><s:propertyvalue="#attr.BB"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用OGNL中的#號(hào)獲取request范圍中的屬性:</td>?????????<tdalign="left"><s:propertyvalue="#request.req"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用OGNL中的#號(hào)獲取session范圍中的屬性:</td>?????????<tdalign="left"><s:propertyvalue="#session.ses"/></td>?????</tr>?????<tr>?????????<tdalign="right">利用OGNL中的#號(hào)獲取Paraments對(duì)象的屬性:</td>?????????<tdalign="left"><s:propertyvalue="#parameters.netname"/></td>?????</tr>?????<tr>?????????<tdalign="right">使用<%=request.getParameter("")%>或者${param.name}獲取鏈接參數(shù)值:</td>?????????<tdalign="left">???????????? ${param.netname}???????????????????<%=request.getParameter("netname")%>?????????</td>?????</tr>?????<tr>?????????<tdalign="right">查看值棧中的信息:</td>?????????<tdalign="left"><s:debug/></td>?????</tr>?</table>? [xhtml]?view plaincopy <%@?page?language="java"?pageEncoding="UTF-8"%>??<%@?taglib?prefix="s"?uri="/struts-tags"%>??<h1>這是使用OGNL輸出的結(jié)果頁(yè)面</h1>??<table?border="9">??????<tr>??????????<td?align="right">獲取姓名屬性:</td>??????????<td?align="left"><s:property?value="user.username"/></td>??????????<%--?另外還有兩種寫法也是可以正常輸出值棧中對(duì)象的普通屬性的?--%>??????????<%--?<s:property?value="user['username']"/>?--%>??????????<%--?<s:property?value="user[/"username/"]"/>?--%>??????????<%--?但是如果寫成下面這種形式的話,就什么都不會(huì)輸出了?--%>??????????<%--?<s:property?value="user[username]"/>?--%>??????</tr>??????<tr>??????????<td?align="right">獲取地址屬性:</td>??????????<td?align="left"><s:property?value="user.address.addr"/></td>??????</tr>??????<tr>??????????<td?align="right">調(diào)用值棧中的對(duì)象的普通方法:</td>??????????<td?align="left"><s:property?value="user.getVOMethod()"/></td>??????</tr>??????<tr>??????????<td?align="right">調(diào)用值棧中Action的普通方法:</td>??????????<td?align="left"><s:property?value="getCommon()"/></td>??????</tr>??</table>??<hr/>??<table?border="9">??????<tr>??????????<td?align="right">獲取普通類的靜態(tài)屬性:</td>??????????<td?align="left"><s:property?value="@com.jadyer.vo.Address@TIPS"/></td>??????</tr>??????<tr>??????????<td?align="right">訪問(wèn)普通類的構(gòu)造方法:</td>??????????<td?align="left"><s:property?value="new?com.jadyer.vo.Student('張小三',22).username"/></td>??????</tr>??????<tr>??????????<td?align="right">調(diào)用Action中的靜態(tài)方法:</td>??????????<td?align="left"><s:property?value="@com.jadyer.action.LoginAction@getStatic()"/></td>??????</tr>??????<tr>??????????<td?align="right">調(diào)用JDK中的類的靜態(tài)方法:</td>??????????<td?align="left"><s:property?value="@java.util.Calendar@getInstance().time"/></td>??????</tr>??????<tr>??????????<td?align="right">調(diào)用JDK中的類的靜態(tài)方法:</td>??????????<td?align="left"><s:property?value="@java.lang.Math@floor(46.58)"/></td>??????</tr>??????<tr>??????????<td?align="right">調(diào)用JDK中的類的靜態(tài)方法:</td>??????????<td?align="left"><s:property?value="@@floor(46.58)"/></td>??????</tr>??</table>??<hr/>??<table?border="9">??????<tr>??????????<td?align="right">獲取List中的所有元素:</td>??????????<td?align="left"><s:property?value="testList"/></td>??????</tr>??????<tr>??????????<td?align="right">獲取Set中的所有元素:</td>??????????<td?align="left"><s:property?value="testSet"/></td>??????</tr>??????<tr>??????????<td?align="right">獲取Map中的所有元素:</td>??????????<td?align="left"><s:property?value="testMap"/></td>??????</tr>??????<tr>??????????<td?align="right">獲取Map中的某個(gè)元素:</td>??????????<td?align="left"><s:property?value="testMap['m22']"/></td>??????????<%--?另外還有兩種寫法也是可以正常獲取Map中的某個(gè)具體元素的?--%>??????????<%--?<s:property?value="testMap.m22"/>?--%>??????????<%--?<s:property?value="testMap[/"m22/"]"/>?--%>??????</tr>??????<tr>??????????<td?align="right">獲取Set中的某個(gè)元素:</td>??????????<%--?由于Set中的元素是無(wú)順序的,所以不能使用下標(biāo)獲取數(shù)據(jù),所以這里什么也得不到?--%>??????????<td?align="left"><s:property?value="testSet[2]"/></td>??????</tr>??????<tr>??????????<td?align="right">獲取List中的某個(gè)元素:</td>??????????<td?align="left"><s:property?value="testList[2]"/></td>??????</tr>??</table>??<hr/>??<table?border="9">??????<tr>??????????<td?align="right">獲取List的大小:</td>??????????<td?align="left"><s:property?value="testList.size"/></td>??????</tr>??????<tr>??????????<td?align="right">獲取Set的大小:</td>??????????<td?align="left"><s:property?value="testSet.size"/></td>??????</tr>??????<tr>??????????<td?align="right">獲取Map的大小:</td>??????????<td?align="left"><s:property?value="testMap.size"/></td>??????</tr>??????<tr>??????????<td?align="right">獲取Map中所有的鍵:</td>??????????<td?align="left"><s:property?value="testMap.keys"/></td>??????</tr>??????<tr>??????????<td?align="right">獲取Map中所有的值:</td>??????????<td?align="left"><s:property?value="testMap.values"/></td>??????</tr>??????<tr>??????????<td?align="right">Lambda計(jì)算4的階乘:</td>??????????<td?align="left"><s:property?value="#f=?:[#this==1?1?:?#this*#f(#this-1)],#f(4)"/></td>??????</tr>??</table>??<hr/>??<table?border="9">??????<tr>??????????<td?align="right">獲取List中的所有對(duì)象:</td>??????????<td?align="left"><s:property?value="stus"/></td>??????</tr>??????<tr>??????????<td?align="right">利用投影獲取List中對(duì)象的名字:</td>??????????<td?align="left"><s:property?value="stus.{username}"/></td>??????</tr>??????<tr>??????????<td?align="right">利用投影獲取List中第二個(gè)對(duì)象的名字:</td>??????????<%--?使用<s:property?value="stus[1].{username}"/>獲取到的值為:[李四]?--%>??????????<%--?二者的區(qū)別在于:后者比前者多了一個(gè)中括號(hào)?--%>??????????<td?align="left">??????????????<s:property?value="stus.{username}[1]"/>????????????????????<s:property?value="stus[1].{username}"/>??????????</td>??????</tr>??????<tr>??????????<td?align="right">利用選擇獲取List中成績(jī)及格的所有對(duì)象:</td>??????????<td?align="left"><s:property?value="stus.{?#this.grade>=60}"/></td>??????</tr>??????<tr>??????????<td?align="right">利用選擇獲取List中成績(jī)及格的第一個(gè)對(duì)象:</td>??????????<td?align="left"><s:property?value="stus.{^#this.grade>=60}"/></td>??????</tr>??????<tr>??????????<td?align="right">利用選擇獲取List中成績(jī)及格的最后一個(gè)對(duì)象:</td>??????????<td?align="left"><s:property?value="stus.{$#this.grade>=60}"/></td>??????</tr>??</table>??<hr/>??<table?border="9">??????<tr>??????????<td?align="right">利用選擇獲取List中成績(jī)及格的所有對(duì)象的名字:</td>??????????<td?align="left"><s:property?value="stus.{?#this.grade>=60}.{username}"/></td>??????</tr>??????<tr>??????????<td?align="right">利用選擇獲取List中成績(jī)及格的第二個(gè)對(duì)象的名字:</td>??????????<td?align="left"><s:property?value="stus.{?#this.grade>=60}.{username}[1]"/></td>??????</tr>??????<tr>??????????<td?align="right">利用選擇獲取List中成績(jī)及格的第一個(gè)對(duì)象的名字:</td>??????????<td?align="left"><s:property?value="stus.{^#this.grade>=60}.{username}"/></td>??????</tr>??????<tr>??????????<td?align="right">利用選擇獲取List中成績(jī)及格的最后一個(gè)對(duì)象的名字:</td>??????????<td?align="left"><s:property?value="stus.{$#this.grade>=60}.{username}"/></td>??????</tr>??????<tr>??????????<td?align="right">利用選擇獲取List中成績(jī)及格的第一個(gè)對(duì)象然后求大小:</td>??????????<td?align="left"><s:property?value="stus.{^#this.grade>=60}.{username}.size"/></td>??????</tr>??</table>??<hr/>??<table?border="9">??????<tr>??????????<td?align="right">利用OGNL中的#號(hào)獲取attr中的屬性:</td>??????????<td?align="left"><s:property?value="#attr.BB"/></td>??????</tr>??????<tr>??????????<td?align="right">利用OGNL中的#號(hào)獲取request范圍中的屬性:</td>??????????<td?align="left"><s:property?value="#request.req"/></td>??????</tr>??????<tr>??????????<td?align="right">利用OGNL中的#號(hào)獲取session范圍中的屬性:</td>??????????<td?align="left"><s:property?value="#session.ses"/></td>??????</tr>??????<tr>??????????<td?align="right">利用OGNL中的#號(hào)獲取Paraments對(duì)象的屬性:</td>??????????<td?align="left"><s:property?value="#parameters.netname"/></td>??????</tr>??????<tr>??????????<td?align="right">使用<%=request.getParameter("")%>或者${param.name}獲取鏈接參數(shù)值:</td>??????????<td?align="left">??????????????${param.netname}????????????????????<%=request.getParameter("netname")%>??????????</td>??????</tr>??????<tr>??????????<td?align="right">查看值棧中的信息:</td>??????????<td?align="left"><s:debug/></td>??????</tr>??</table>?? 然后是struts.xml文件 [xhtml]?view plaincopy <?xmlversion="1.0"encoding="UTF-8"?>?<!DOCTYPE struts PUBLIC???? "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"???? "http://struts.apache.org/dtds/struts-2.0.dtd">?<struts>?????<packagename="ognl"extends="struts-default">?????????<actionname="login"class="com.jadyer.action.LoginAction">?????????????<resultname="input">/login.jsp</result>?????????????<resultname="success">/loginSuc.jsp?netname=hongyu</result>???????????? <!--?????????????<resultname="success"type="redirect">/loginSuc.jsp?netname=hongyu</result>?????????????<resultname="success"type="redirect">/loginSuc.jsp?netname=${user.username}</result>?????????????? -->?????????</action>?????</package>?</struts>? [xhtml]?view plaincopy <?xml?version="1.0"?encoding="UTF-8"?>??<!DOCTYPE?struts?PUBLIC??????"-//Apache?Software?Foundation//DTD?Struts?Configuration?2.0//EN"??????"http://struts.apache.org/dtds/struts-2.0.dtd">??<struts>??????<package?name="ognl"?extends="struts-default">??????????<action?name="login"?class="com.jadyer.action.LoginAction">??????????????<result?name="input">/login.jsp</result>??????????????<result?name="success">/loginSuc.jsp?netname=hongyu</result>??????????????<!--??????????????<result?name="success"?type="redirect">/loginSuc.jsp?netname=hongyu</result>??????????????<result?name="success"?type="redirect">/loginSuc.jsp?netname=${user.username}</result>????????????????-->??????????</action>??????</package>??</struts>?? 接著是用到的三個(gè)VO類 ? [java]?view plaincopy package?com.jadyer.vo;?publicclass?User {?????private?String username;?????private?String password;?????private?Address address;?????/* 三個(gè)屬性的setter和getter略 */?????public?String getVOMethod(){?????????return"這是User類中的一個(gè)普通方法";???? }?}???package?com.jadyer.vo;?publicclass?Address {?????//如果將TIPS設(shè)為private的話,loginSuc.jsp中就無(wú)法獲取它的屬性值了?????//事實(shí)上將一個(gè)靜態(tài)的final屬性設(shè)為private是毫無(wú)意義的?????//因?yàn)榧热辉O(shè)置成了靜態(tài),那么就是供他人調(diào)用的,如果再設(shè)成private的話,別的地方根本就無(wú)法調(diào)用了?????//即使OGNL再怎么強(qiáng)大,它也不可能違反Java的規(guī)則,所以不要將靜態(tài)的屬性設(shè)為私有?????publicstaticfinal?String TIPS =?"玄玉加油!!";?????//addr屬性的setter和getter略?????private?String addr;?}???package?com.jadyer.vo;?publicclass?Student {?????private?String username;?????privateint?grade;?????/* 兩個(gè)屬性的setter和getter略 */??????????//只要是重寫一個(gè)類的構(gòu)造方法,就必須要為這個(gè)類保留空的構(gòu)造方法?????//因?yàn)榭蚣苣J(rèn)的都會(huì)去調(diào)用無(wú)參的空的構(gòu)造方法?????public?Student(){};?????public?Student(String username,int?grade){?????????this.username = username;?????????this.grade = grade;???? }?????@Override?????public?String toString() {?????????//如果不重寫它的toString()方法的話,默認(rèn)調(diào)用toString()將輸出【類型+@+內(nèi)存地址的哈希值】?????????return"{學(xué)生姓名:"?+ username +",成績(jī):"?+ grade +?"}";???? }?}? [java]?view plaincopy package?com.jadyer.vo;??public?class?User?{??????private?String?username;??????private?String?password;??????private?Address?address;??????/*?三個(gè)屬性的setter和getter略?*/??????public?String?getVOMethod(){??????????return?"這是User類中的一個(gè)普通方法";??????}??}??????package?com.jadyer.vo;??public?class?Address?{??????//如果將TIPS設(shè)為private的話,loginSuc.jsp中就無(wú)法獲取它的屬性值了??????//事實(shí)上將一個(gè)靜態(tài)的final屬性設(shè)為private是毫無(wú)意義的??????//因?yàn)榧热辉O(shè)置成了靜態(tài),那么就是供他人調(diào)用的,如果再設(shè)成private的話,別的地方根本就無(wú)法調(diào)用了??????//即使OGNL再怎么強(qiáng)大,它也不可能違反Java的規(guī)則,所以不要將靜態(tài)的屬性設(shè)為私有??????public?static?final?String?TIPS?=?"玄玉加油!!";??????//addr屬性的setter和getter略??????private?String?addr;??}??????package?com.jadyer.vo;??public?class?Student?{??????private?String?username;??????private?int?grade;??????/*?兩個(gè)屬性的setter和getter略?*/????????????//只要是重寫一個(gè)類的構(gòu)造方法,就必須要為這個(gè)類保留空的構(gòu)造方法??????//因?yàn)榭蚣苣J(rèn)的都會(huì)去調(diào)用無(wú)參的空的構(gòu)造方法??????public?Student(){};??????public?Student(String?username,int?grade){??????????this.username?=?username;??????????this.grade?=?grade;??????}??????@Override??????public?String?toString()?{??????????//如果不重寫它的toString()方法的話,默認(rèn)調(diào)用toString()將輸出【類型+@+內(nèi)存地址的哈希值】??????????return?"{學(xué)生姓名:"?+?username?+?",成績(jī):"?+?grade?+?"}";??????}??}?? 最后是用來(lái)提供OGNL測(cè)試的數(shù)據(jù)的LoginAction.java [java]?view plaincopyprint? package?com.jadyer.action;? ? import?java.util.ArrayList;? import?java.util.HashMap;? import?java.util.HashSet;? import?java.util.List;? import?java.util.Map;? import?java.util.Set;? ? import?org.apache.struts2.interceptor.RequestAware;? import?org.apache.struts2.interceptor.SessionAware;? ? import?com.jadyer.vo.Student;? import?com.jadyer.vo.User;? import?com.opensymphony.xwork2.ActionSupport;? ? @SuppressWarnings({"serial","unchecked"})? publicclass?LoginActionextends?ActionSupport?implements?RequestAware,SessionAware {? ????private?User user;? ????private?List testList =?new?ArrayList();? ????private?Set testSet =new?HashSet();? ????private?Map testMap =?new?HashMap();? ????private?List stus =?new?ArrayList();? ????? ????/* 以上五個(gè)屬性的setter和getter略 */? ????? ????private?Map request;? ????private?Map session;? ????publicvoid?setRequest(Map request) {? ????????this.request = request;? ??? }? ????publicvoid?setSession(Map session) {? ????????this.session = session;? ??? }? ????? ????publicstatic?String getStatic(){? ????????return"這是LoginAction中的一個(gè)靜態(tài)方法";? ??? }? ????public?String getCommon(){? ????????return"這是LoginAction中的一個(gè)普通方法";? ??? }? ????? ????@Override? ????public?String execute()?throws?Exception {? ????????if(user.getUsername().trim().equalsIgnoreCase("admin") && user.getPassword().equals("jadyer")){? ??????????? testList.add("list11");? ??????????? testList.add("list22");? ??????????? testList.add("list33");? ??????????? testList.add("list44");? ??????????? testList.add("list55");? ????????????? ??????????? testSet.add("set11");? ??????????? testSet.add("set22");? ??????????? testSet.add("set33");? ??????????? testSet.add("set22");? ??????????? testSet.add("set11");? ????????????? ??????????? testMap.put("m11",?"map11");? ??????????? testMap.put("m22","map22");? ??????????? testMap.put("m33",?"map33");? ??????????? testMap.put("m44","map44");? ??????????? testMap.put("m55",?"map55");? ????????????? ??????????? stus.add(new?Student("張三",88));? ??????????? stus.add(new?Student("李四",77));? ??????????? stus.add(new?Student("王五",66));? ??????????? stus.add(new?Student("馬六",55));? ????????????? ??????????? request.put("req","這是通過(guò)OGNL中的#號(hào)獲取的request屬性范圍的值");? ??????????? session.put("ses",?"這是通過(guò)OGNL中的#號(hào)獲取的session屬性范圍的值");? ??????????? request.put("BB","這是通過(guò)OGNL中的#號(hào)獲取的request屬性范圍的BB");? ??????????? session.put("BB",?"這是通過(guò)OGNL中的#號(hào)獲取的session屬性范圍的BB");? ????????????return?SUCCESS;? ??????? }else{? ????????????return?INPUT;? ??????? }? ??? }???? } ? |