JSTL詳解(八)
9.8?Struts 與 JSTL
9.8.1?JSTL
與
Struts
協(xié)同工作
作為
( 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ù)一大堆資源配置文件哪個更方便呢?
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)簽來完成判斷的
表 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é)果,這樣的程序
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é)
posted on 2007-01-18 15:21 nbt 閱讀(3977) 評論(1) 編輯 收藏 所屬分類: Servele&JSP和js