在這一小節(jié)中,將修改在第三章中曾經(jīng)給出的
Struts
框架示例,以
Struts
框架和
JSTL
的協(xié)同工作來實(shí)現(xiàn)。
對(duì)于第三章的示例,要將
JSTL
整合進(jìn)去,需要做以下幾步工作。
(
1
)下載
JSTL
并配置。
(
1
)修改原先的
web.xml
使其作為
Servlet2.4
的實(shí)現(xiàn)。
(
3
)修改
JSP
顯示頁面,整合
JSTL
和
Struts
標(biāo)簽庫一起工作。
可以從
http://java.sun.com/products/jsp/jstl
網(wǎng)址中下載
JSTL1.1
的最新版本。要使用這些標(biāo)簽庫需要做
3
個(gè)步驟的工作。
(
1
)將下載的
jstl.jar
放置到
Web
應(yīng)用的
WEB-INF
的
lib
目錄下。
(
2
)將下載的
TLD
文件放置到
Web
應(yīng)用的
WEB-INF
目錄下。
(
3
)在需要使用的
JSP
頁面中聲明該標(biāo)簽庫。
9.9.2?
修改
web.xml
使其作為
Servlet2.4
的實(shí)現(xiàn)
在第三章的示例中所給出的
web.xml
是
Servlet2.3
規(guī)范的,因此無法很好的支持
JSTL1.1
,要修改為符合
Servlet2.4
規(guī)范的代碼。使
web.xml
成為
Servlet2.4
規(guī)范是十分容易的,需要修改的是其頭部
DTD
聲明。
在
Servlet2.3
之前,校驗(yàn)和規(guī)范
web.xml
都是使用
DTD
,因此其頭部聲明如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
…
</web-app>
而到了
Servlet2.4
規(guī)范,首此使用了
xmlns
來聲明
web.xml
,因此其頭部聲明為:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
???????? xmlns="http://java.sun.com/xml/ns/j2ee"
???????? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
???????? xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
????????
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd
">
…
</web-app>
所以,為了支持
Servlet2.4
規(guī)范,應(yīng)該將第三章示例的
web.xml
改成如例
9.6
的樣子。
例
9.6
:修改后的
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
???????? xmlns="http://java.sun.com/xml/ns/j2ee"
???????? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
???????? xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
???????? http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
?<filter>
????? <filter-name>Set Character Encoding</filter-name>
????? <filter-class>struts.sample.cap1.sample3.util.SetCharacterEncodingFilter</filter-class>
????? <init-param>
??????????????? <param-name>encoding</param-name>
??????????????? <param-value>UTF-8</param-value>
????? </init-param>
?</filter>
?<filter-mapping>
????? <filter-name>Set Character Encoding</filter-name>
????? <url-pattern>*.do</url-pattern>
?</filter-mapping>
?<servlet>
??? <servlet-name>action</servlet-name>
??? <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
??? <init-param>
????? <param-name>config</param-name>
????? <param-value>/WEB-INF/struts-config.xml</param-value>
??? </init-param>
??? <init-param>
????? <param-name>debug</param-name>
????? <param-value>2</param-value>
??? </init-param>
??? <load-on-startup>1</load-on-startup>
?</servlet>
?<servlet-mapping>
??? <servlet-name>action</servlet-name>
??? <url-pattern>*.do</url-pattern>
?</servlet-mapping>
?<welcome-file-list>
??? <welcome-file>setSolution.jsp</welcome-file>
?</welcome-file-list>
?<taglib>
??? <taglib-uri>/WEB-INF/struts-template.tld</taglib-uri>
??? <taglib-location>/WEB-INF/struts-template.tld</taglib-location>
?</taglib>
?<taglib>
??? <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
??? <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
?</taglib>
?<taglib>
??? <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
??? <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
?</taglib>
?<taglib>
??? <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
??? <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
?</taglib>
?<taglib>
??? <taglib-uri>/WEB-INF/struts-template.tld</taglib-uri>
??? <taglib-location>/WEB-INF/struts-template.tld</taglib-location>
?</taglib>
?<taglib>
??? <taglib-uri>/WEB-INF/struts-tiles.tld</taglib-uri>
??? <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>
?</taglib>
?<taglib>
??? <taglib-uri>/WEB-INF/struts-nested.tld</taglib-uri>
??? <taglib-location>/WEB-INF/struts-nested.tld</taglib-location>
?</taglib>
</web-app>
修改的地方不多,僅僅是頭部的聲明。其他地方完全不必改動(dòng),這樣的
web.xml
已經(jīng)支持了
Servlet2.4
規(guī)范了。
9.9.3?JSP
部分:
<logic:notEmpty>
和
<c:if>
標(biāo)簽
對(duì)于
JSP
顯示頁面的修改是整合的核心部分,在第三章示例的
showAttackSolution.jsp
中出現(xiàn)了這樣的語句:
<logic:notEmpty name="allAttackSolution">
...
</logic:notEmpty>
將類型為
ArrayList
的變量“
allAttackSolution
”從作用范圍中取出,利用
<logic:notEmpty>
標(biāo)簽判斷該
ArrayList
是否為空。
根據(jù)之前討論的“所有判斷標(biāo)簽被
EL
表達(dá)式和
<c:if>
標(biāo)簽替換”,可以利用
<c:if>
標(biāo)簽和
EL
表達(dá)式來修改該段
JSP
代碼。
修改后的結(jié)果如下:
<c:if test="${(requestScope.allAttackSolution != null)
&& fn:length(requestScope.allAttackSolution) != 0}">
...
</c:if>
<logic:notEmpty>
標(biāo)簽其本身具有多種功能:
q????????
一是判斷是否為
null
。
q????????
二是當(dāng)它為
String
類型的變量時(shí),判斷字符串長(zhǎng)度是否為
0
。
q????????
三是當(dāng)它為集合類型的變量時(shí),利用集合類的
isEmpty
方法可以判斷是否是一個(gè)空的集合。
本示例既然要在替換后與替換前的工作一致,就應(yīng)該對(duì)集合做兩個(gè)判斷:
q????????
一是該集合不為
null
。
q????????
二是該集合中的對(duì)象數(shù)量不為
0
。
“
!=null
”的
EL
表達(dá)式實(shí)現(xiàn)了集合實(shí)例不為
null
的判斷;
fn:length()
函數(shù)實(shí)現(xiàn)了集合內(nèi)對(duì)象數(shù)量不為
0
的判斷,兩個(gè)判斷用“
&&
”連接起來就實(shí)現(xiàn)了
<logic:notEmpty>
標(biāo)簽對(duì)于集合判斷的工作。
在這里應(yīng)該利用“
<logic:notEmpty>
標(biāo)簽”,還是利用“
EL
表達(dá)式和
<c:if>
標(biāo)簽”呢?
<logic:notEmpty>
標(biāo)簽相對(duì)來說可讀性更強(qiáng)些,
EL
表達(dá)式作為判斷條件則可讀性稍差些。然而,這些僅是就本示例的改動(dòng)而言的,其他情況下,利用
EL
表達(dá)式和
<c:if>
標(biāo)簽還是有其優(yōu)勢(shì)的。
9.9.4?JSP
部分:
<logic:iterate>
和
<c:forEach>
標(biāo)簽
在第三章示例的
showAttackSolution.jsp
中出現(xiàn)了這樣的使用:
<logic:iterate name="allAttackSolution"
id="attackSolution"
type="struts.sample.cap1.sample3.entity.AttackSolution">
???????? <tr>
?????????????????? <td style="word-break: break-all;">
??????????????????????????? <bean:write property="attack_event_code" name="attackSolution" />
?????????????????? </td>
?????????????????? <td style="word-break: break-all;">
??????????????????????????? <bean:write property="attack_mean" name="attackSolution" />
?????????????????? </td>
?????????????????? <td style="word-break: break-all;">
??????????????????????????? <bean:write property="attack_action" name="attackSolution" />
?????????????????? </td>
?????????????????? <td style="word-break: break-all;">
??????????????????????????? <input type="button"
??????????????????? onclick="del('<%=attackSolution.getAttack_event_code()%>');"
value="<bean:message key="message.delete"/>">
?????????????????? </td>
???????? </tr>
</logic:iterate>
由于在
Action
中將顯示的內(nèi)容作為
ArrayList
類型的實(shí)例保存在
request
中,因此這段
JSP
頁面標(biāo)簽的工作是:
(
1
)利用
<logic:iterate>
標(biāo)簽對(duì)保存在
ArrayList
實(shí)例中的所有對(duì)象進(jìn)行循環(huán)取得。
(
2
)
ArrayList
類型實(shí)例中的對(duì)象為
struts.sample.cap1.sample3.entity.AttackSolution
類型,
AttackSolution Java
類中的變量屬性都有
get
、
set
方法,因此可以被認(rèn)為是一個(gè)標(biāo)準(zhǔn)的
JavaBean
。利用
<bean:write>
標(biāo)簽將
AttackSolution
實(shí)例的變量屬性讀取出來,并顯示。
根據(jù)之前討論的“
<logic:iterate>
標(biāo)簽被
<c:forEach>
標(biāo)簽和
EL
表達(dá)式替換”,可以利用
<c:forEach>
標(biāo)簽和
EL
表達(dá)式來修改該段
JSP
代碼。修改的方式有兩種:
q????????
完全使用
<c:forEach>
標(biāo)簽和
EL
表達(dá)式來替換全部。
q????????
僅使用
EL
表達(dá)式來替換
<bean:write>
標(biāo)簽。
1. <c:forEach>
標(biāo)簽和
EL
表達(dá)式
<c:forEach>
標(biāo)簽和
EL
表達(dá)式:
<c:forEach items="${requestScope.allAttackSolution}"
var="attackSolution">
???????? <tr>
????????
???????? <td style="word-break: break-all;" >
??????????????????????????? ${attackSolution.attack_event_code}
?????????????????? </td>
?????????????????? <td style="word-break: break-all;" >
??????????????????????????? ${attackSolution.attack_mean}
?????????????????? </td>
?????????????????? <td style="word-break: break-all;" >
??????????????????
???????? ${attackSolution.attack_action}
?????????????????? </td>
?????????????????? <td style="word-break: break-all;" >
<input type="button"
onclick="del('${attackSolution.attack_event_code}');"
value="<bean:message key="message.delete"/>">
</td>
???????? </tr>
</c:forEach>
這種修改方式將屏棄
Struts
框架的
<logic:iterate>
標(biāo)簽,而以
<c:forEach>
標(biāo)簽來作為循環(huán)迭代的工作。它的最大優(yōu)點(diǎn)是無需關(guān)注集合中的對(duì)象類型,只要保證該對(duì)象是一個(gè)標(biāo)準(zhǔn)的
JavaBean
就可以了。
2.
使用
EL
表達(dá)式來替換
<bean:write>
標(biāo)簽
<logic:iterate name="allAttackSolution"
id="attackSolution"
type="struts.sample.cap1.sample3.entity.AttackSolution">
???????? <tr>
?????????????????? <td style="word-break: break-all;" >
??????????????????
??? ${attackSolution.attack_event_code}
?????????????????? </td>
?????????????????? <td style="word-break: break-all;" >
??????????????????
??? ${attackSolution.attack_mean}
?????????????????? </td>
?????????????????? <td style="word-break: break-all;" >
??????????????????
??? ${attackSolution.attack_action}
?????????????????? </td>
?????????????????? <td style="word-break: break-all;" >
<input type="button"
onclick="del('${attackSolution.attack_event_code}');"
value="<bean:message key="message.delete"/>">
</td>
???????? </tr>
</logic:iterate>
這種方式對(duì)原來的代碼沒有做多大的改動(dòng),依然會(huì)使用
<logic:iterate>
標(biāo)簽來作為循環(huán)標(biāo)簽。不過對(duì)于原來使用
<bean:write>
標(biāo)簽做顯示功能的地方,摒棄了
<bean:write>
標(biāo)簽而直接使用
EL
表達(dá)式。靈活的
EL
表達(dá)式對(duì)頁面顯示邏輯有很大幫助,這種方式比較適合熟悉
<logic:iterate>
標(biāo)簽的程序設(shè)計(jì)者。
下面看一個(gè)完整的修改后
JSP
頁面的代碼,注釋掉的是被替換之前的代碼,讀者可以比較一下兩種實(shí)現(xiàn)方法。請(qǐng)見例
9.7
。
例
9.7
:修改后
showAttackSolution.jsp
。
<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<html>
?<head>
??? <!--
略過
JavaScript
部分
-->
...
?</head>
?<body>
?? <em><bean:message key="message.attacksolutionDB"/></em><p>
?? <table>
??????? <html:errors/>
??? </table>
<bean:message key="message.attackcode"/>:
<input name="attack_event_codeC" value="" type="text">
<bean:message key="message.attackdesc"/>:
<TEXTAREA style="height:100" name=attack_meanC></TEXTAREA>
<bean:message key="message.attacksolution"/>:
<TEXTAREA style="height:100" name=attack_actionC></TEXTAREA>
??? <p/>
??? <html:form action="AddAttackSolutionAction.do">
??????? <html:hidden property="attack_event_code"/>
??????? <html:hidden property="attack_mean"/>
??????? <html:hidden property="attack_action"/>
??????? <input type="button" onclick="add();" value="<bean:message key="message.add"/>">
??????? <input type="button"?
onclick="search();"
value="<bean:message key="message.search"/>">
??? </html:form>
??? <table border=1 cellspacing=1 cellpadding=2>
??????? <tr>
??????????? <td style="background-color: #808080;font-size: 12pt;color: #ffffff;font-weight:
?bold;line-height: 15pt;border: 1px solid #808080;">
??????????????? <bean:message key="message.attackcode"/>
??????????? </td>
??????????? <td style="background-color: #808080;font-size: 12pt;color: #ffffff;font-weight:
?bold;line-height: 15pt;border: 1px solid #808080;">
??????????????? <bean:message key="message.attackdesc"/>
??????????? </td>
??????????? <td style="background-color: #808080;font-size: 12pt;color: #ffffff;font-weight:
?bold;line-height: 15pt;border: 1px solid #808080;">
??????????????? <bean:message key="message.attacksolution"/>
??????????? </td>
??????????? <td style="background-color: #808080;font-size: 12pt;color: #ffffff;font-weight:
?bold;line-height: 15pt;border: 1px solid #808080;">
??????????????? <bean:message key="message.delete"/>
??????????? </td>
??????? </tr>
??????? <!--
沒有替換前的代碼
-->
??????? <!--
??????????? <logic:notEmpty name="allAttackSolution">
??????????????? <logic:iterate name="allAttackSolution"
id="attackSolution"
type="struts.sample.cap1.sample3.entity.AttackSolution">
??????????????????? <tr>
??????????????????????? <td style="word-break: break-all;" >
??????????????????????????? <bean:write property="attack_event_code"
name="attackSolution"/>
??????????????????????? </td>
??????????????????????? <td style="word-break: break-all;" >
??????????????????????????? <bean:write property="attack_mean" name="attackSolution"/>
??????????????????????? </td>
??????????????????????? <td style="word-break: break-all;" >
??????????????????????????? <bean:write property="attack_action" name="attackSolution"/>
??????????????????????? </td>
??????????????????????? <td style="word-break: break-all;" >
??????????????????????????? <input type="button"
onclick="del('
<bean:write
property="attack_event_code"
name="attackSolution"/>');"
value="<bean:message key="message.delete"/>">
??????????????????????? </td>
??????????????????? </tr>
??????????????? </logic:iterate>
??????????? </logic:notEmpty>
??????? -->
??
?????
??????? <!--
僅替換
<bean:write>
標(biāo)簽的代碼
-->
??????? <!--
??????????? <logic:notEmpty name="allAttackSolution">
??????????????? <logic:iterate name="allAttackSolution"
id="attackSolution"
type="struts.sample.cap1.sample3.entity.AttackSolution">
?????????
??????????<tr>
??????????????????????? <td style="word-break: break-all;" >
??????????????????????????? ${attackSolution.attack_event_code}
??????????????????????? </td>
??????????????????????? <td style="word-break: break-all;" >
????????????????????????
???${attackSolution.attack_mean}
??????????????????????? </td>
??????????????????????? <td style="word-break: break-all;" >
??????????????????????????? ${attackSolution.attack_action}
??????????????????????? </td>
??????????????????????? <td style="word-break: break-all;" >
??????????????????????????? <input type="button"
onclick="del('${attackSolution.attack_event_code}');"
value="<bean:message key="message.delete"/>">
??????????????????????? </td>
??????????????????? </tr>
??????????????? </logic:iterate>
??????????? </logic:notEmpty>
??????? -->
???????
??????? <!--
替換后的實(shí)現(xiàn)代碼
-->??????
??????? <c:if test="${(requestScope.allAttackSolution != null)
&& fn:length(requestScope.allAttackSolution) != 0}">
??????????? <c:forEach items="${requestScope.allAttackSolution}" var="attackSolution">
??????????????? <tr>
??????????????????? <td style="word-break: break-all;" >
??????????????????????? ${attackSolution.attack_event_code}
??????????????????? </td>
??????????????????? <td style="word-break: break-all;" >
??????????????????????? ${attackSolution.attack_mean}
??????????????????? </td>
??????????????????? <td style="word-break: break-all;" >
??????????????????????? ${attackSolution.attack_action}
??????????????????? </td>
??????????????????? <td style="word-break: break-all;" >
??????????????????????? <input type="button"
????????????????????????????? onclick="del('${attackSolution.attack_event_code}');"
value="<bean:message key="message.delete"/>">
??????????????????? </td>
??????????????? </tr>
??????????? </c:forEach>
??????? </c:if>
??? </table>
?</body>
</html>
可以看到,在這個(gè)被修改的
JSP
頁面代碼中,利用了
Struts
框架提供的標(biāo)簽來實(shí)現(xiàn)提交部分的工作以及國(guó)際化資源配置文件讀取顯示的工作,也利用
JSTL
的標(biāo)簽庫和
EL
表達(dá)式來實(shí)現(xiàn)頁面邏輯部分的工作。
在
JSP
頁面使用
JSTL
是一種規(guī)范,也是一件令人興奮的事情,因?yàn)樗?/span>
JSP
部分的程序設(shè)計(jì)變得更加有效合理。