JSTL詳解(八)

          9.8?Struts JSTL

          9.8.1?JSTL Struts 協(xié)同工作

          作為服務(wù)器端表示層 MVC 經(jīng)典框架的 Struts ,其突出表現(xiàn)就是在表示層頁面流轉(zhuǎn)方面。雖然在顯示的視圖層, Struts 框架提供了一組功能強(qiáng)大的標(biāo)簽庫來幫助運(yùn)用。但是這組標(biāo)簽庫還是比較復(fù)雜,例如要取得一個 Session 中的 JavaBean ,需要做兩個步驟的動作。

          1 )使用 <bean:define> 標(biāo)簽來定義一個目標(biāo) JavaBean 的標(biāo)識,并從 Session 中取得源 JavaBean 賦給目標(biāo) JavaBean 。若該 JavaBean 本身是 String 類型,則只需要設(shè)置它的 name 屬性,否則還需要設(shè)置 property 屬性。

          2 )使用 <bean:write> 標(biāo)簽將該 JavaBean 的變量屬性顯示出來。若該 JavaBean 本身是 String 類型,則只需要設(shè)置它的 name 屬性,否則還需要設(shè)置 property 屬性。

          下面看一個示例,假設(shè) Session 中有一個參數(shù)為“ TEST ”,其值為 String 類型的字符串“ hello ”。那么使用 Struts 框架的 <bean> 標(biāo)簽庫的代碼就應(yīng)該是這樣:

          <bean:define id="test" name="TEST" scope="session"/>

          <bean:write name="test"/>

          定義一個目標(biāo) JavaBean 的標(biāo)識“ test ”,然后將從 Session 中的參數(shù)“ TEST ”所取得的源 JavaBean 的實(shí)例賦給目標(biāo) JavaBean 。 <bean:write> 標(biāo)簽會根據(jù) <bean:define> 標(biāo)簽的 id 屬性設(shè)置自身的 name 屬性,來獲取目標(biāo) JavaBean 并顯示出來。由于它們操作的是 String 類型的字符串,因此編碼還算比較簡單。可是,如果它們操作的是一個非 String 類型的 JavaBean ,那么編碼就比較麻煩了。

          如果使用的是 JSTL ,這部分的操作就十分簡單了,僅僅通過 EL 表達(dá)式語言就可以完成了,轉(zhuǎn)換成 EL 表達(dá)式的操作編碼如下:

          ${sessionScope.TEST}

          轉(zhuǎn)換成 JSTL ,只要一句表達(dá)式就已經(jīng)完成了 <bean> 標(biāo)簽庫需要用兩個標(biāo)簽和許多屬性才能完成的工作。即使使用的是 JavaBean 中的屬性, JSTL 表達(dá)式也只需要再加個“ . ”操作符而已。

          使用 JSTL 中的 EL 表達(dá)式和 JSTL 標(biāo)簽庫中的標(biāo)簽,可以簡化 Struts 標(biāo)簽庫中許多標(biāo)簽的操作。下面就根據(jù)具體的對比來進(jìn)行介紹。

          9.8.2?JSTL VS Struts Bean 標(biāo)簽庫

          Struts Bean 標(biāo)簽庫在 EL 表達(dá)式?jīng)]有出現(xiàn)前是十分常用的,無論從 Session 、 request 、 page 或是其他作用范圍( Scope )中取得參數(shù)、或者從標(biāo)準(zhǔn) JavaBean 中讀取變量屬性都處理得得心應(yīng)手。然而,在 EL 表達(dá)式出現(xiàn)之后, Struts Bean 標(biāo)簽庫的標(biāo)簽在操作的時候就顯示出了煩瑣的缺點(diǎn)。因此用 EL 表達(dá)式來替代 Struts Bean 標(biāo)簽庫中的標(biāo)簽是一種較好的做法。

          1. <bean:define> 標(biāo)簽和 <bean:write> 標(biāo)簽處理顯示被 EL 表達(dá)式替換

          q???????? 原形: <bean:define> 標(biāo)簽的作用是定義一個 JavaBean 類型的變量,從 Scope 源位置得到該 JavaBean 的實(shí)例。 <bean:write> 標(biāo)簽可以通過 JavaBean 變量來做顯示的工作。

          q???????? 替換方案:利用 EL 表達(dá)式來替換。

          q???????? 示例比較

          <bean:define> 標(biāo)簽和 <bean:write> 標(biāo)簽的動作:

          <bean:define id="javaBeanName"

          name="javaBeanParameter"

          property="javaBeanProperty"

          scope="request"/>

          <bean:write name="javaBeanName"/>

          EL 表達(dá)式的動作:

          ${requestScope.javaBeanParameter.javaBeanProperty}

          ${requestScope.javaBeanParameter['javaBeanProperty’]}

          處理相同的一個動作,使用 define 標(biāo)簽,通常需要記住各種屬性的功能,并有選擇地根據(jù)實(shí)際情況來挑選是否需要 property 屬性,還要指定其 scope 屬性。而 EL 表達(dá)式就方便多了,直接使用默認(rèn)變量 pageScope 、 requestScope 、 sessionScope 、 applicationScope 指定源 JavaBean 作用范圍,利用“ . ”操作符來指定 JavaBean 的名稱以及利用“ [] ”或“ . ”來指定 JavaBean 中的變量屬性。

          q???????? 比較結(jié)果:無論是可讀性還是程序的簡潔性方面, EL 表達(dá)式無疑要勝過許多,唯一的缺點(diǎn)是 EL 表達(dá)式必須使用 Servlet2.4 以上的規(guī)范。

          2. <bean:cookie> 、 <bean:header> <bean:parameter> 標(biāo)簽和 <bean:write> 標(biāo)簽處理顯示被 EL 表達(dá)式替換

          q???????? 原形: <bean:cookie> 、 <bean:header> 、 <bean:parameter> 標(biāo)簽的作用是,定義一個 JavaBean 類型的變量,從 cookie request header 、 request parameter 中得到該 JavaBean 實(shí)例。 <bean:write> 標(biāo)簽可以通過 JavaBean 變量來做顯示的工作。

          q???????? 替換方案:利用 EL 表達(dá)式來替換。

          q???????? 示例比較: <bean:parameter> 標(biāo)簽的動作:

          <bean:parameter id="requestString" name="requestParameterString" />

          <bean:write name="requestString"/>

          EL 表達(dá)式的動作:

          ${param.requestParameterString}

          q???????? 比較結(jié)果: EL 表達(dá)式默認(rèn)的 5 個變量: cookie 、 header 、 headerValues paramValues 、 param 完全可以提供更方便簡潔的操作。

          3. <bean:include> 標(biāo)簽被 <c:import> 標(biāo)簽替換

          q???????? 原形: <bean:include> 標(biāo)簽的作用是定義一個 String 類型的變量,可以包含一個頁面、一個響應(yīng)或一個鏈接。

          q???????? 替換方案:利用 <c:import> 標(biāo)簽來替換。

          q???????? 示例比較

          <bean:include> 標(biāo)簽的動作:

          <bean:include page="/MyHtml.html" id="thisurlPage" />

          <c:import> 標(biāo)簽的動作:

          <c:import url="/MyHtml.html" var="thisurlPage" />

          <bean:include> 標(biāo)簽的 page 屬性所起的作用可以由 <c:import> 標(biāo)簽來替換,二者的操作結(jié)果是一樣的。

          q???????? 比較結(jié)果:這一對標(biāo)簽的比較沒有明顯區(qū)別,而 <bean:include> 標(biāo)簽有更多屬性提供更多功能,因此替換并不是十分必要。

          尤其是當(dāng)要用到配置在 struts-config.xml 中的 <global-forwards> 元素進(jìn)行全局轉(zhuǎn)發(fā)頁面時,必須使用 <bean:include> 標(biāo)簽的 forward 元素來實(shí)現(xiàn)。

          4. <bean:message> 標(biāo)簽處理資源配置文件被 <fmt:bundle> <fmt:setBundle> 、 <fmt:message> 標(biāo)簽合作替換

          q???????? 原形: <bean:message> 標(biāo)簽是專門用來處理資源配置文件顯示的,而它的資源配置文件被配置在 struts-config.xml <message-resources> 元素中。

          q???????? 替換方案:利用 <fmt:bundle> 、 <fmt:setBundle> 、 <fmt:message> 標(biāo)簽合作來替換,由 <fmt:bundle> 、 <fmt:setBundle> 設(shè)置資源配置文件的實(shí)體名稱,再由 <fmt:message> 標(biāo)簽負(fù)責(zé)讀取顯示。

          q???????? 示例 比較

          <bean:message> 標(biāo)簽的動作:

          <bean:message key="message.attacksolution"/>

          <fmt:bundle> 、 <fmt:message> 標(biāo)簽的動作:

          <fmt:bundle basename="resources.application">

          ???????? <fmt:message key="message.attacksolution" />

          </fmt:bundle>

          <fmt:setBundle> 、 <fmt:message> 標(biāo)簽的動作:

          <fmt:setBundle basename="resources.application" var="resourceaApplication"/>

          <fmt:message key="message.attacksolution" bundle="${resourceaApplication}"/>

          q???????? 比較結(jié)果:這一對標(biāo)簽對于國際化的支持都相當(dāng)好,唯一最大的區(qū)別在于利用 <bean:message> 標(biāo)簽所操作的資源配置文件是配置在 struts-config.xml 中的,而 <fmt:message> 標(biāo)簽所操作的資源配置文件則是根據(jù) <fmt:bundle> 、 <fmt:setBundle> 兩組標(biāo)簽來得到的。看起來,后者的靈活性不錯,但就筆者的眼光來看,前者更為規(guī)范,對于用戶協(xié)作的要求也更高。試想,維護(hù)一到兩個資源配置文件與維護(hù)一大堆資源配置文件哪個更方便呢?自然是前者了,因此除非是不依賴 Struts 框架的應(yīng)用,否則最好使用 <bean:message> 標(biāo)簽。

          9.8.3?JSTL VS Struts Logic 標(biāo)簽庫

          Struts Logic 標(biāo)簽庫中的標(biāo)簽在頁面顯示時是時常被用到的,但是常用的卻不一定是最好用的,有了 JSTL 標(biāo)簽庫和 EL 表達(dá)式后,許多 Struts Logic 標(biāo)簽庫的標(biāo)簽可以被簡單替換。

          1. 所有判斷標(biāo)簽被 EL 表達(dá)式和 <c:if> 標(biāo)簽替換

          q???????? 原形:判斷標(biāo)簽有一個特點(diǎn),就是需要取得一個實(shí)例的變量,因此通過 <bean:define> 標(biāo)簽來取得實(shí)例的變量是必須的,隨后就通過各種判斷標(biāo)簽來完成判斷的工作。常用的判斷標(biāo)簽如表 9.30 所示:

          9.30? 常用判斷標(biāo)簽

          標(biāo)簽名

          描述

          empty

          判斷變量是否為空

          notEmpty

          empty 標(biāo)簽正好相反

          equal

          判斷變量是否與指定的相同

          notEqual

          equal 標(biāo)簽正好相反

          lessThan

          判斷變量是否比指定的小

          greaterThan

          判斷變量是否比指定的大

          lessEqual

          判斷變量是否小于等于指定的值

          greaterEqual

          判斷變量是否大于等于指定的值

          present

          檢查 header 、 request parameter cookie 、 JavaBean JavaBean propertie 不存在或等于 null 的時候,判斷成功

          notPresent

          present 標(biāo)簽正好相反

          match

          比較 String 類型字符串是否與指定的相同

          notMatch

          match 標(biāo)簽正好相反

          q???????? 替換方案:利用 EL 表達(dá)式和 <c:if> 標(biāo)簽來替換。

          q???????? 示例比較:判斷標(biāo)簽的動作:

          <bean:define id="javaBeanName"

          name="javaBeanParameter"

          property="attack_event_code"

          scope="request"/>

          <logic:notEmpty name="javaBeanParameter">

          ???????? javaBeanParameter not empty

          </logic:notEmpty>

          EL 表達(dá)式和 <c:if> 標(biāo)簽的動作:

          <c:if test="${requestScope.javaBeanParameter.attack_event_code != null

          && requestScope.javaBeanParameter.attack_event_code != ''”}>

          ???????? javaBeanParameter not empty

          </c:if>

          EL 表達(dá)式利用操作符來完成判斷動作,然后通過 <c:if> 標(biāo)簽來根據(jù)判斷結(jié)果處理對應(yīng)工作。

          q???????? 比較結(jié)果: EL 表達(dá)式的操作符對判斷的貢獻(xiàn)很大, EL 表達(dá)式的靈活性是 Struts 判斷標(biāo)簽無法比擬的,任何判斷標(biāo)簽都可以通過表達(dá)式來實(shí)現(xiàn)。 <c:if> 標(biāo)簽還可以將判斷的結(jié)果保存為一個變量,隨時為之后的頁面處理服務(wù)。

          反觀 Struts 框架的判斷標(biāo)簽,在工作之前必須先定義被判斷的變量,而判斷后又無法保存判斷結(jié)果,這樣的程序設(shè)計遠(yuǎn)不如 EL 表達(dá)式和 <c:if> 標(biāo)簽的協(xié)作來得強(qiáng)大。因此使用 EL 表達(dá)式和 <c:if> 標(biāo)簽來替換判斷標(biāo)簽是更好的選擇。

          2. <logic:iterate> 標(biāo)簽被 <c:forEach> 標(biāo)簽和 EL 表達(dá)式替換

          q???????? 原形: <logic:iterate> 標(biāo)簽用來對集合對象的迭代,可以依次從該集合中取得所需要的對象。

          q???????? 替換方案:利用 <c:forEach> 標(biāo)簽和 EL 表達(dá)式的協(xié)作替換 <logic:iterate> 標(biāo)簽。

          q???????? 示例比較

          <logic:iterate> 標(biāo)簽的動作:

          <logic:iterate name="allAttackSolution"

          ???? id="attackSolution"

          ???? type="struts.sample.cap1.sample3.entity.AttackSolution">

          ???????? <bean:write property="attack_event_code" name="attackSolution"/>

          ???????? <bean:write property="attack_mean" name="attackSolution"/>

          ???????? <bean:write property="attack_action" name="attackSolution"/>

          </logic:iterate>

          <c:forEach> 標(biāo)簽 EL 表達(dá)式協(xié)作的動作:

          <c:forEach items="${requestScope.allAttackSolution}" var="attackSolution">

          ???????? ${attackSolution.attack_event_code}

          ???????? ${attackSolution.attack_mean}

          ???????? ${attackSolution.attack_action}

          </c:forEach>

          兩個動作都做的是同一件事,從 request 中得到保存的“ allAttackSolution ”參數(shù),該參數(shù)為一個集合,集合中的對象為 struts.sample.cap1.sample3.entity.AttackSolution 類型的實(shí)例。

          <logic:iterate> 標(biāo)簽本身可以接收集合,保存為一個變量,利用迭代子模式,使 <logic:iterate> 標(biāo)簽體中的 <bean:write> 標(biāo)簽將集合中的每個 JavaBean 顯示出來。

          提示:在本例中由于要顯示 JavaBean 中的變量屬性,因此 <bean:write> 標(biāo)簽還需要設(shè)置 property 屬性。

          替換工作的 <c:forEach> 標(biāo)簽則相對要方便些, items 屬性使用 EL 表達(dá)式取得集合,然后設(shè)置 var 屬性作為集合中對象的變量,最后使用 EL 表達(dá)式來顯示數(shù)據(jù)。

          q???????? 比較結(jié)果:

          值得注意的一個地方是, <logic:iterate> 標(biāo)簽必須為集合中的對象指定類型,因?yàn)闃?biāo)簽庫處理時會將集合中的對象作為 Object 類型得到,然后需要讀取 type 屬性定義的 Java 類為它強(qiáng)制轉(zhuǎn)型。

          <c:forEach> 標(biāo)簽則完全不用,只要符合標(biāo)準(zhǔn) JavaBean (為變量屬性提供 get set 方法)的對象都可以通過 EL 表達(dá)式來從 var 屬性定義的變量中取得該 JavaBean 的變量屬性。

          因此 <c:forEach> 標(biāo)簽和 EL 表達(dá)式的方式更加簡單,也更加靈活。

          當(dāng)然,熟悉 <logic:iterate> 標(biāo)的程序設(shè)計者也可以將 <bean:write> 標(biāo)簽替換為 EL 表達(dá)式而仍然使用 <logic:iterate> 標(biāo)簽。代碼可以是這樣:

          <logic:iterate name="allAttackSolution"

          id="attackSolution"

          type="struts.sample.cap1.sample3.entity.AttackSolution">

          ???????? ${attackSolution.attack_event_code}

          ???????? ${attackSolution.attack_mean}

          ???????? ${attackSolution.attack_action}

          </logic:iterate>

          結(jié)果一樣,但這種方式比 <bean:write> 標(biāo)簽顯示方式靈活多了。

          3. <logic:redirect> 標(biāo)簽被 <c:redirect> <c:param> 標(biāo)簽替換

          q???????? 原形: <logic:redirect> 標(biāo)簽用來轉(zhuǎn)發(fā)到一個頁面,并可以為轉(zhuǎn)發(fā)傳遞參數(shù)。

          q???????? 替換方案:利用 <c:redirect> <c:param> 標(biāo)簽的協(xié)作替換 <logic:redirect> 標(biāo)簽。

          q???????? 示例比較: <logic:iterate> 標(biāo)簽的動作:

          <%

          ???????? HashMap paramMap = new HashMap();

          ???????? paramMap.put("userName", "RW");

          ???????? paramMap.put("passWord", "123456");

          %>

          ?<logic:redirect page="/MyHtml.jsp" name="paramMap" scope="request" />

          <c:redirect> <c:param> 標(biāo)簽協(xié)作的動作:

          <c:redirect url="/MyHtml.jsp">

          ???????? <c:param name="userName" value="RW"/>

          ???????? <c:param name="passWord" value="123456"/>

          </c:redirect>

          兩個動作都做的是同一件事,都將轉(zhuǎn)發(fā)到當(dāng)前 Web Context 下的“ MyHtml.jsp ”去,而且都將為它提供兩個參數(shù)。最后的轉(zhuǎn)發(fā)鏈接看起來應(yīng)該如下所示:

          http://localhost:8080/test/ MyHtml.jsp? userName=RW&password=123456

          q???????? 比較結(jié)果

          一眼就可以看出, <logic:redirect> 標(biāo)簽的可讀性不強(qiáng),它的 name 屬性表示的是一個 Map 類型的變量。如果還有 property 屬性,則 name 屬性指的是一個標(biāo)準(zhǔn) JavaBean 。 property 屬性指的是 JavaBean 中的一個 Map 類型的變量屬性,通過 Map 的“名值對”來為轉(zhuǎn)發(fā)頁面?zhèn)鬟f參數(shù)。如果轉(zhuǎn)發(fā)參數(shù)是來自于一個 Map JavaBean 中的 Map 類型變量屬性,那還好,因?yàn)榭梢栽?/span> Java 類中處理??墒侨绻兇馐菑捻撁嫔先〉媚承┲底鳛檗D(zhuǎn)發(fā)參數(shù),那就困難了,必須像本示例所給出的那樣,自行定義一個 Map 實(shí)例。這種情況下,頁面就會看到 Java 語言的片段,既麻煩又不符合標(biāo)準(zhǔn)。

          而使用 <c:redirect> <c:param> 標(biāo)簽協(xié)作,由于包含在 <c:redirect> 標(biāo)簽體內(nèi)的 <c:param> 標(biāo)簽可以有多個,因此顯式地提供 <c:param> 標(biāo)簽就完成了給出轉(zhuǎn)發(fā)參數(shù)的工作,即使用到 JavaBean ,也可以使用 EL 表達(dá)式來實(shí)現(xiàn)。

          綜上所述,利用 <c:redirect> <c:param> 標(biāo)簽來代替 <logic:redirect> 標(biāo)簽是有必要的。

          9.8.4? 總結(jié)

          Struts 框架和 JSTL 并不是互相沖突的兩種技術(shù),雖然 Struts 框架提供了功能不錯的標(biāo)簽庫,但是使用 JSTL 可以簡化 Struts 框架標(biāo)簽庫復(fù)雜的地方,這對于服務(wù)器端表示層框架的 Struts 來說幫助很大。 Struts HTML 標(biāo)簽庫無法使用 JSTL 來替換,但是,使用 EL 表達(dá)式作為一些 value 屬性,來做賦值的工作仍然不失為一種好的選擇。因此,在 JSTL 已經(jīng)比較成熟的今天,使用 Struts 框架和 JSTL 整合來作 JSP 頁面將使程序設(shè)計更為輕松。


          posted on 2007-01-18 15:21 nbt 閱讀(3977) 評論(1)  編輯  收藏 所屬分類: Servele&JSP和js

          評論

          # re: JSTL詳解(八) 2007-10-25 13:26 xuelei

          s  回復(fù)  更多評論   

          <2007年1月>
          31123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導(dǎo)航

          統(tǒng)計

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          相冊

          收藏夾

          Java技術(shù)網(wǎng)站

          友情鏈接

          國內(nèi)一些開源網(wǎng)站

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 桐梓县| 东乡| 遂宁市| 闸北区| 太康县| 景德镇市| 修水县| 盈江县| 苗栗市| 婺源县| 治多县| 子洲县| 德江县| 丹棱县| 简阳市| 封丘县| 昆明市| 商水县| 丹阳市| 家居| 石渠县| 丽水市| 新沂市| 保德县| 崇州市| 许昌县| 抚顺县| 黔江区| 含山县| 渝北区| 隆化县| 东阳市| 英吉沙县| 九江县| 临湘市| 惠水县| 共和县| 西吉县| 紫阳县| 林周县| 青河县|