JSTL詳解(八)

          9.8?Struts JSTL

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

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

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

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

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

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

          <bean:write name="test"/>

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

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

          ${sessionScope.TEST}

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

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

          9.8.2?JSTL VS Struts Bean 標簽庫

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

          1. <bean:define> 標簽和 <bean:write> 標簽處理顯示被 EL 表達式替換

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

          q???????? 替換方案:利用 EL 表達式來替換。

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

          <bean:define> 標簽和 <bean:write> 標簽的動作:

          <bean:define id="javaBeanName"

          name="javaBeanParameter"

          property="javaBeanProperty"

          scope="request"/>

          <bean:write name="javaBeanName"/>

          EL 表達式的動作:

          ${requestScope.javaBeanParameter.javaBeanProperty}

          ${requestScope.javaBeanParameter['javaBeanProperty’]}

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

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

          2. <bean:cookie> <bean:header> <bean:parameter> 標簽和 <bean:write> 標簽處理顯示被 EL 表達式替換

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

          q???????? 替換方案:利用 EL 表達式來替換。

          q???????? 示例比較: <bean:parameter> 標簽的動作:

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

          <bean:write name="requestString"/>

          EL 表達式的動作:

          ${param.requestParameterString}

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

          3. <bean:include> 標簽被 <c:import> 標簽替換

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

          q???????? 替換方案:利用 <c:import> 標簽來替換。

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

          <bean:include> 標簽的動作:

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

          <c:import> 標簽的動作:

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

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

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

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

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

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

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

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

          <bean:message> 標簽的動作:

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

          <fmt:bundle> <fmt:message> 標簽的動作:

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

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

          </fmt:bundle>

          <fmt:setBundle> <fmt:message> 標簽的動作:

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

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

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

          9.8.3?JSTL VS Struts Logic 標簽庫

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

          1. 所有判斷標簽被 EL 表達式和 <c:if> 標簽替換

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

          9.30? 常用判斷標簽

          標簽名

          描述

          empty

          判斷變量是否為空

          notEmpty

          empty 標簽正好相反

          equal

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

          notEqual

          equal 標簽正好相反

          lessThan

          判斷變量是否比指定的小

          greaterThan

          判斷變量是否比指定的大

          lessEqual

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

          greaterEqual

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

          present

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

          notPresent

          present 標簽正好相反

          match

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

          notMatch

          match 標簽正好相反

          q???????? 替換方案:利用 EL 表達式和 <c:if> 標簽來替換。

          q???????? 示例比較:判斷標簽的動作:

          <bean:define id="javaBeanName"

          name="javaBeanParameter"

          property="attack_event_code"

          scope="request"/>

          <logic:notEmpty name="javaBeanParameter">

          ???????? javaBeanParameter not empty

          </logic:notEmpty>

          EL 表達式和 <c:if> 標簽的動作:

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

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

          ???????? javaBeanParameter not empty

          </c:if>

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

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

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

          2. <logic:iterate> 標簽被 <c:forEach> 標簽和 EL 表達式替換

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

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

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

          <logic:iterate> 標簽的動作:

          <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> 標簽 EL 表達式協(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 類型的實例。

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

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

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

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

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

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

          因此 <c:forEach> 標簽和 EL 表達式的方式更加簡單,也更加靈活。

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

          <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> 標簽顯示方式靈活多了。

          3. <logic:redirect> 標簽被 <c:redirect> <c:param> 標簽替換

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

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

          q???????? 示例比較: <logic:iterate> 標簽的動作:

          <%

          ???????? 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> 標簽協(xié)作的動作:

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

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

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

          </c:redirect>

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

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

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

          一眼就可以看出, <logic:redirect> 標簽的可讀性不強,它的 name 屬性表示的是一個 Map 類型的變量。如果還有 property 屬性,則 name 屬性指的是一個標準 JavaBean property 屬性指的是 JavaBean 中的一個 Map 類型的變量屬性,通過 Map 的“名值對”來為轉(zhuǎn)發(fā)頁面?zhèn)鬟f參數(shù)。如果轉(zhuǎn)發(fā)參數(shù)是來自于一個 Map JavaBean 中的 Map 類型變量屬性,那還好,因為可以在 Java 類中處理。可是如果純粹是從頁面上取得某些值作為轉(zhuǎn)發(fā)參數(shù),那就困難了,必須像本示例所給出的那樣,自行定義一個 Map 實例。這種情況下,頁面就會看到 Java 語言的片段,既麻煩又不符合標準。

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

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

          9.8.4? 總結(jié)

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


          posted on 2007-01-18 15:21 nbt 閱讀(3979) 評論(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)站

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 溧阳市| 双牌县| 义马市| 庆元县| 沙河市| 射洪县| 二连浩特市| 大姚县| 辽源市| 寿光市| 修水县| 普格县| 临武县| 孝昌县| 荣成市| 宝丰县| 汝州市| 黎川县| 新营市| 大方县| 平果县| 延吉市| 新河县| 江门市| 临漳县| 桂平市| 道真| 阜宁县| 博罗县| 论坛| 将乐县| 金昌市| 鸡泽县| 芦溪县| 资兴市| 咸丰县| 华宁县| 九寨沟县| 合水县| 囊谦县| 湟源县|