posts - 78, comments - 34, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          2010-02-21 傳智播客—Struts2

          Posted on 2010-02-22 16:59 長城 閱讀(743) 評論(0)  編輯  收藏

          Struts2第二天,大家似乎沒有從年假中蘇醒過來,上課顯得有些疲憊。不過還好,聽課效果還不錯。今日的主要內(nèi)容是OGNLStruts2使用OGNL訪問contextMapvalueStack。老張很執(zhí)著,他在研究Struts2時遇到的一些問題,一定要解決,并且要詳細解決。通過他在講課中,我們可以看出這一點。有開發(fā)經(jīng)驗的人都知道,我們時而被陌生技術(shù)的一個小細節(jié)搞的暈頭轉(zhuǎn)向,耗費了大半天的時間我們才發(fā)現(xiàn)這個細節(jié)性的錯誤。我們一般都是這么熬出來的,老張也不例外。


          我們在聽老師講課時或在網(wǎng)上看視頻時,都感覺學(xué)習(xí)起來十分容易。卻很少有人能感受那些認真負責(zé)老師在課后付出的心血。老張為了準(zhǔn)備一天的課程內(nèi)容,使用了三天時間來備課并且課程內(nèi)容他以前也講過。這一點不僅體現(xiàn)在老張的身上,其他老師也是這樣。讓我們?yōu)槟切┱J真負責(zé)的老師敬禮,并問候一聲:“過年好,您辛苦了!”。


          一、ActionContext

          Action環(huán)境(com.opensymphony.xwork2.ActionContext),通過我們之前所學(xué)的內(nèi)容。我們知道Context緩存中保存了XXX環(huán)境中所需要使用到的重要對象。Struts2中的ActionContext中就保存了Struts2中使用到的重點對象contextMapvalueStack。


          老張搞了一個經(jīng)典的關(guān)系圖:


          ActionContext ac = ActionContext.getContext();

          ValueStack vs = ac.getValueStack();

          Map<String, Object> conMap = ac.getContextMap();

          每一個訪問線程具有一個ActionContext對象,它是以單例模式存在的。ActionContext為我們提供了操作valueStackcontextMap的便捷方法。例我們的程序可以與ValueStackContextMap解耦,比如:ac.put(key, value);ac.get(key);...


          通過ActionContext使得我們編寫的Action不必實現(xiàn)任何接口和繼承任何超類,但我們必須在類中使用ActionContext的實例。


          二、Struts2中的OGNL

          OGNL不是Struts2獨創(chuàng)的,而是Struts2中使用OGNL做為操作contextMapvalueStack的方式。OGNLObject-Graph Navigation Language的縮寫,它是一種功能強大的表達式語言(Expression Language,簡稱為EL),通過它簡單一致的表達式語法,可以存取對象的任意屬性,調(diào)用對象的方法,遍歷整個對象的結(jié)構(gòu)圖,實現(xiàn)字段類型轉(zhuǎn)化等功能。它使用相同的表達式去存取對象的屬性。


          OGNLl基本的語法:

          1. 可以用#key的形式訪問OGNL Context對象中的各個key對應(yīng)的對象,并可以采用點(.)操作符進行多級導(dǎo)航調(diào)用對象的屬性和方法,例如,#application#session.attr1#key1.sayHello();對于map對象,map.attr不是map.getAttr()方法,而是表示map.get(“attr1”)

          2. 如果要訪問根對象的屬性或方法,則可以省略#key,直接訪問該對象的屬性和方法。 struts2修改了OGNL表達式的默認屬性訪問器,它不是直接訪問根對象ValueStack的屬性或方法,而是在ValueStack內(nèi)部的堆棧中所有對象上逐一查找該屬性或方法,搜索順序是從棧頂對象開始尋找,依次往下,直到找到為止,例如,sayHello()表示調(diào)用堆棧中某個對象的sayHello()方法。

          3. 特例:如果引用名前面沒有#,且valueStack中存儲的各個對象沒有該屬性,則把該名稱當(dāng)作Context對象中的某個key來檢索對應(yīng)的對象,但這種方式不支持點(.)操作符。


          ValueStack提供了如下一些方法管理其內(nèi)部的堆棧和關(guān)聯(lián)的Context

          1. setValueognl表達式尋址到的對象設(shè)置屬性值。

          2. FindValue方法使用OGNL表達式獲取結(jié)果。

          3. findString方法對findValue方法獲取的結(jié)果調(diào)用轉(zhuǎn)換器轉(zhuǎn)成字符串,如果該對象的類型沒有相關(guān)轉(zhuǎn)換器,則調(diào)用toString方法,并返回結(jié)果字符串。一個特殊之處:如果不用#前綴訪問ValueStack Context中的對象,則該對象必須是String類型。


          三、Struts2中的struts-tagsOGNL詳細

          要使用struts-tags標(biāo)簽,必須先引入struts-2.1.7.dtd文檔類型定義文件。

          1. <s:property>用于輸出某個OGNL表達式的值,可以認為其內(nèi)部使用的是ValueStack對象的findString方法。如果沒有設(shè)置value屬性,則輸出ValueStack棧頂?shù)膶ο蟆?/span>

            特例:如果采用不加#前綴的方式輸出Context中的某個對象,這個對象必須是string類型。

            如:獲取contextMap中的request對象。

            <s:property value="#request" />

          2. <s:push>用于將OGNL表達式的值壓入棧頂,當(dāng)遇到</s:push>標(biāo)簽時,從棧頂彈出。

            如:向棧頂壓入了一個字符串——“你好!”。

            <s:push value="'你好!'">

            <s:property value="top" />

            </s:push>

            注意壓入的字符串必須被包含在''中,否則會被OGNL當(dāng)做名稱到根對象中查找相應(yīng)的值。

            通過查看<s:push>標(biāo)簽的幫助,可以知道有一個為top的特殊OGNL表達式,表示棧頂?shù)膶ο蟆?/font>

            如:

          <s:push value="'你好!'"><s:property name="top"/></s:push>


          1. <s:bean>用于實例化一個JavaBean對象,并將其壓入棧頂。如果設(shè)置了var屬性,還會將實例化的對象存儲進ValueStack關(guān)聯(lián)的Context中。

            如:實例化一個java.util.Date對象,然后將其放入ContextMap中。

            <s:bean name="java.util.Date" var="MyBean">

            <s:property value="#MyBean" />

            </s:bean>

          2. <s:set>用于將某個值存入指定范圍域中,通常用于將一個復(fù)雜的ognl表達式用一個簡單的變量來進行引用。

            如:向request域中添加一個名稱為“TestSet”的屬性。

            <s:set scope="request" value="'日期'+#MyBean" name="TestSet">

            <s:property value="#request.TestSet" />

            </s:set>

            scope屬性:指定變量被放置的范圍,該屬性可以接受application、sessionrequest、 pageaction。該屬性的默認值為action,文檔說即表示同時存儲進request作用域和OGNL Context中,但實驗結(jié)果是只存儲進了OGNL Context中。

            value屬性:賦給變量的ognl表達式結(jié)果.如果沒有設(shè)置該屬性,則將ValueStack棧頂?shù)闹蒂x給變量。

          3. <s:if/elseif/else>等標(biāo)簽用于判斷test屬性中指定的ognl表達式的結(jié)果是否為true,為真則執(zhí)行標(biāo)簽體重的內(nèi)容。

            如:設(shè)置一個VAL,然后判斷VAL的值,并顯示相應(yīng)的結(jié)果。

            <s:set value="'1'" name="VAL"></s:set>

            <s:if test="1 > 2">

            <s:property value="#VAL+'>2'" />

            </s:if>

            <s:elseif test="1 < 2">

            <s:property value="#VAL+'<2'" />

            </s:elseif>

            <s:else>

            <s:property value="#VAL+'=2'" />

            </s:else>

          4. <s:iterator>用于迭代一個OGNL集合,并逐一將迭代出來的元素壓入棧頂和彈棧。

            如:獲取request中的所有屬性,并且使表格奇數(shù)行顏色為#f3c3c3,偶數(shù)行顏色為#c3f3f3。

            <table>

            <tr>

            <td>Key</td><td>Value</td>

            </tr>

            <s:iterator value="#request" status="status">

            <tr bgcolor='<s:property value="#status.odd ? '#f3c3c3':'#c3f3f3'"/>' >

            <td><s:property value="key"/></td>

            <td><s:property value="value"/></td>

            </tr>

            </s:iterator>

            </table>

            status屬性:創(chuàng)建代表當(dāng)前迭代狀態(tài)的IteratorStatus對象,并指定將其存儲進ValueStack Context中時的key。它與官方給出的幫助文檔的說明不同,官方存在錯誤!

          5. <s:url><s:a>

            使用這兩個標(biāo)簽可以帶給我們極大的方便,使用他們的好處有:

            使用<s:url namespace=“” action=“” method=“”/>不用關(guān)心web應(yīng)用程序的路徑和Action映射的擴展名。<s:url>中沒有指定namespace屬性時,將根據(jù)瀏覽器當(dāng)前所訪問的url地址來推測包名,并與action屬性指定的內(nèi)容一起生成最終的url地址。

            可以自動附加jsessionid參數(shù)進行url重寫。

            可以對參數(shù)信息進行url編碼。 (jstl中的<c:url>標(biāo)準(zhǔn)標(biāo)簽也有<s:url>標(biāo)簽的后兩個作用。)

            直接使用<s:url />標(biāo)簽可以獲得當(dāng)前地址,只有使用includeParams屬性會帶上原來的請求參數(shù)。大型網(wǎng)站的鏈接地址總是要帶上userid之類的信息。

            如:生成一個訪問我們昨天編寫的HelloWorld請求超連接。

            <s:a namespace="/" action="helloWorld" method="helloWorld">HelloWorld</s:a>

          四、OGNL中的語法細節(jié)

          1.參看ognl的參考手冊

          類似EL表達式的JavaBean屬性訪問和索引訪問,例如,可以用”#parameter.id[0]”或”#parameter[‘id’][0]”訪問名稱為id的請求參數(shù)。

          支持類靜態(tài)方法調(diào)用和屬性訪問,表達式的格式為@[類全名(包括包路徑)]@[方法名 | 值名],例如:@java.lang.String@format(‘foo %s’, ‘bar’)@cn.itcast.Constant@APP_NAME;

          session.attribute[“foo”]等效于session.getAttribute(“foo”)方法。

          OGNL中可以寫很大的整數(shù),例如,<s:property value="%{1111111111111111111111H.bitLength()}"/>,而在java中則不能直接寫1111111111111111111111這么大的整數(shù)。

          對當(dāng)前值可以進一步操作,<s:property value=“110H.intValue().(#this<112?#this*2:#this/2)”/>,其中.(#this …..)部分相當(dāng)于定義了一個匿名方法,并調(diào)用這個匿名方法,方法的代碼就是()里面的內(nèi)容。


          2.Struts2擴展的特殊功能

          [n]表示從原來堆棧中截取一個子堆棧并對這個子堆棧進行操作,子堆棧為原始堆棧的棧頂開始的索引號為n的元素一直到棧底,例如,[1].age表示從原始堆棧中的索引號為1的對象(即第二個對象)開始查找age屬性,以找到的第一個為準(zhǔn)。

          top表示ValueStack棧頂?shù)膶ο螅?/font>[0].toptop表示同一個對象。


          3.集合對象與操作

          {}用于創(chuàng)建List集合對象,其中的各個元素之間用逗號分隔:

          <s:set value="{1,3,5,7}" var="list"/>


          采用類似Java的語法創(chuàng)建數(shù)組:

          <s:set value="new int[]{1,3,5,7}" var="array"/>

          <s:set value="new int[4]" var="array"/>

          #{}用于創(chuàng)建Map集合對象,其中的各個元素之間用逗號分隔,元素的keyvalue之間采用冒號分隔。另外,還可以指定Map實例對象的類型:

          <s:set value="#{'lhm':96,'zxx':93,'xpc':97}" />

          <s:set value="#@java.util.LinkedHashMap@{'lhm':96,'zxx':93,'xpc':97}" />

          innot in操作符用于判斷某個值是否位于某個集合中。

          <s:set value="new int[]{1,3,5,7}" var="array"/>

          <s:if test="1 in #array">

          <s:property value="#array"/>

          </s:if>

          集合偽屬性:size/isEmpty/iterator/keys/values/next/hasNext

          <s:set value="#{'lhm':96,'zxx':93,'xpc':97}" var="map"/>

          <s:if test="#map.size > 0">

          <s:property value="#map"/>

          </s:if>


          4.集合的投影與過濾

          投影就是拿著集合中的每個元素去進行運算,各個元素運算的結(jié)果組成一個新集合,新集合中的元素個數(shù)與原始集合中的元素個數(shù)相同。

          <s:property value="persons.{name}"/>

          <s:property value="{5,3,2}.{#this*2}"/>

          過濾就是拿著集合中的每個元素去進行布爾運算,運算的結(jié)果為true,則將該元素保存到新集合中去。

          ?:獲得所有符合邏輯的元素。

          <s:property value="{5,3,2,0}.{? #this }"/>

          ^:獲得符合邏輯的第一個元素。

          <s:property value="{5,3,2,0}.{^ #this>3 }"/>

          $:獲得符合邏輯的最后一個元素。

          <s:property value="{5,3,2,0}.{$ #this>2 }"/>


          5.類型轉(zhuǎn)換

          轉(zhuǎn)換成boolean類型:

          • 整數(shù)0轉(zhuǎn)換為fals

          • 值為0的字符轉(zhuǎn)化為false

          • Null對象轉(zhuǎn)化為false

          投影和選擇操作符(e1.{e2} and e1.{?e2})里面的內(nèi)容會被轉(zhuǎn)換成集合

          Map會被轉(zhuǎn)化成其values屬性返回的集合

          數(shù)字會被轉(zhuǎn)換成從0開始到比該數(shù)字小1的所有數(shù)字的集合。

          單個對象被轉(zhuǎn)換成僅僅只含有該對象的集合。


          五、在配置文件中使用OGNL

          在下堂課中會做總結(jié)!



          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 昌图县| 博兴县| 成武县| 大新县| 巫山县| 三门县| 广元市| 金门县| 沙坪坝区| 安义县| 贵溪市| 新化县| 琼海市| 安远县| 东港市| 马边| 鲜城| 澎湖县| 南郑县| 资中县| 嘉定区| 鄂托克旗| 依兰县| 吴堡县| 安阳市| 松桃| 石首市| 酒泉市| 沁阳市| 新宾| 仙居县| 揭东县| 高阳县| 潍坊市| 太仆寺旗| 长寿区| 砚山县| 沿河| 泾源县| 梅河口市| 弋阳县|