作者:禪樓望月
1 安裝JSTL1.1①需要將"jstl.jar"和"standard.jar"放在Web應用的WEB-INF/lib目錄中。
②jsp頁面引用JSTL標準標簽 <%@taglibjava.sun.com/jsp/jstl/core"%> ,若uri不知道是什么,則可以打開/java Resources/Libraies/web App Librarues目錄下的standars.jar包下META-INF目錄下c.tld(xml文件)里面查找,如圖所示:
③最后在頁面直接使用JSTL標準標簽庫。
2 <c:out>用來顯示一個表達式的結果,與<%= %>作用相似。
<c:out>標簽有如下屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
value | 要輸出的內容 | 是 | 無 |
default | 輸出的默認值 | 否 | 主體中的內容 |
escapeXml | 是否忽略XML特殊字符 | 否 | true |
①顯式地聲明轉換XML實體
1 <div>2 <b>Tip of the Day:</b><br/><br/>3 <c:outvalue="${pageContent.rawHTML}"escapeXml="true"/>4 </div>View Code
②顯式地聲明不轉換XML實體
將escapeXml設置為false即可。
escapeXml默認值為true。
以下5種字符需要轉換
字符 | < | > | & | ' | " |
字符實體碼 | < | > | & | & | " |
<c:out value="<hr>原樣輸出HTML標簽<hr>" escapeXml="true"/><br> <c:out value="<hr>轉換HTML標簽并輸出<hr>" escapeXml="false"/>
使用EL輸出用戶輸入的內容會存在"跨域攻擊"的危險
跨域攻擊是指,一個用戶使用你的web應用作為傳輸機制向另一個用戶的web瀏覽器發動攻擊。
用<c:out>則可以避免這種情況。
2.1 NULL值的處理EL遇到NULL值什么也不會打印。但是<c:out>可以設置默認值:
value值為NULL時,默認值
<c:out value="${null }"default="houhou"></c:out><br>3 循環<c:forEach>
<c:forEach>標簽有如下屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
items | 要被循環的信息 | 否 | 無 |
begin | 開始的元素(0=第一個元素,1=第二個元素) | 否 | 0 |
end | 最后一個元素(0=第一個元素,1=第二個元素) | 否 | Last element |
step | 每一次迭代的步長 | 否 | 1 |
var | 代表當前條目的變量名稱 | 否 | 無 |
varStatus | 代表循環狀態的變量名稱 | 否 | 無 |
Servlet中:
1 package jstl; 2 import java.io.IOException; 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 public class jstlServlet extendsHttpServlet{ 6 public void doGet(HttpServletRequest request,HttpServletResponse response) 7 throwsServletException,IOException{ 8 response.setContentType("text/html"); 9 String[] movieList={"A","B","C"};10 request.setAttribute("movieList", movieList);11 getServletContext().getRequestDispatcher("/UseJSTL.jsp").forward(request, response);12 }13 publicvoid doPost(HttpServletRequest request,HttpServletResponse response)14 throwsServletException,IOException{15 doGet(request, response);16 }17 }View Code
JSP中:
1 <%@ page language="java"import="java.util.*" pageEncoding="utf-8" %> 2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 4 <html> 5 <head> 6 </head> 7 <body> 8 <table> 9 <c:forEachvar="movie"items="${movieList }">10 <tr>11 <td>${movie }</td>12 </tr>13 </c:forEach>14 </table>15 </body>16 </html>View Code
打印出的結果:
還可用一個可選屬性(varStatus)得到計數器
1 <tablestyle="border:solid 1px red">2 <c:forEachvar="movie"items="${movieList }"varStatus="movieLoopCount">3 <tr>4 <tdstyle="border:solid 1px red">${movie}</td>5 <tdstyle="border:solid 1px red">count:${movieLoopCount.count }</td>6 </tr>7 </c:forEach>8 </table>View Code
<c:forEach>可以嵌套,如:
Servlet中:
JSP中:
關于步長:
還可以有begin和end屬性來選取集合的一個子集。
對map和set的迭代:
<c:if>標簽有如下屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
test | 條件 | 是 | 無 |
var | 用于存儲條件結果的變量 | 否 | 無 |
scope | var屬性的作用域 | 否 | page |
<c:choose>標簽沒有屬性。
<c:when>標簽只有一個屬性,在下表中有給出。
<c:otherwise>標簽沒有屬性。
<c:when>標簽的屬性如下:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
test | 條件 | 是 | 無 |
<c:choose>可以沒有<c:otherwise>
<c:set>標簽有如下屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
value | 要存儲的值 | 否 | 主體的內容 |
target | 要修改的屬性所屬的對象 | 否 | 無 |
property | 要修改的屬性 | 否 | 無 |
var | 存儲信息的變量 | 否 | 無 |
scope | var屬性的作用域 | 否 | Page |
<jsp:setProperty> 只能設置bean的屬性。但是<c:set>可以設置任何東西的值。
<c:set> 有兩版本:① var 版本,用來設置屬性變量;②target 版本,用來bean性質或Map值,但是不能用來向數組或列表中增加元素。
① var 版本
<c:setvar=""scope=""value=""/> 使用var來定義變量。
②target 版本
<c:set> 要點
7 <c:remove> 移除一個變量①不能同時有var和target。
②scope是可選的,默認值為頁面(page)作用域,即,沒有scope時,只會在頁面(page)作用域中查找。
③如果value為null,則var指定的屬性將被刪除
④若var屬性不存在,則會創建一個新屬性,但僅當value不為null時才會創建新屬性。
⑤若target表達式為null,容器拋異常。
⑥若target表達式不是bean或map,容器拋異常。
⑦若target表達式是一個bean,但是這個bean沒有與property匹配的屬性,容器拋異常。EL表達式${bean.notAProperty}也會拋異常
<c:remove>標簽有如下屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
var | 要移除的變量名稱 | 是 | 無 |
scope | 變量所屬的作用域 | 否 | 所有作用域 |
<c:import>標簽有如下屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
url | 需要檢索和引入的頁面的URL | 是 | 無 |
context | / 緊接著一個本地網絡應用程序的名稱 | 否 | 當前應用程序 |
charEncoding | 所引入的數據的字符編碼集 | 否 | ISO-8859-1 |
var | 用于存儲所引入的文本的變量 | 否 | Print to page |
scope | var屬性的作用域 | 否 | Page |
varReader | 可選的用于提供java.io.Reader對象的變量 | 否 | 無 |
第一種:靜態導入<%@include file="/index.jsp"%>
第二種:動態導入<jsp:includepage="index.jsp"/>
第三種:動態導入<c:importurl="http://www.baidu.com"/>
在請求時將URL屬性值制定的內容增加到當前頁面。與<jsp:include>非常相似但是功能更加強大。前兩種被被包含的頁面不能超出本站范圍,但是<c:import可以。
也可以利用<c:param傳參數。
<c:param>標簽用于在<c:url>標簽中指定參數,而且與URL編碼相關。
在<c:param>標簽內,name屬性表明參數的名稱,value屬性表明參數的值。
<c:param>標簽有如下屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
name | URL中要設置的參數的名稱 | 是 | 無 |
value | 參數的值 | 否 | Body |
<c:url>標簽有如下屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
value | 基礎URL | 是 | 無 |
context | 本地網絡應用程序的名稱 | 否 | 當前應用程序 |
var | 代表URL的變量名 | 否 | Print to page |
scope | var屬性的作用域 | 否 | Page |
<c:url>可以自動實現URL重寫。
Servlet的URL重寫:
JSP的URL重寫:
URL編碼:
URL通常需要編碼。意思是,把不安全/保留的字符替換為其他字符,然后再在服務器端完成解碼。
例子:
加入URL中不能包含空格,但是可用一個+“+”來代替。
<c:url>不會自動對URL編碼。
在無法保證一個錯誤都沒有的情況下,更友好的解決方式是建立一個錯誤響應頁面,然后使用page指令配置錯誤頁面。
①設計一個錯誤響應頁面:
②為有可能出現錯誤的頁面配置錯誤頁面:
問題來了---->我是不是得花很大的功夫為每一個jsp配置錯誤頁面呢?如果想為不同的錯誤制定不同的錯誤頁面怎辦呢?
在DD中可以根據<exception-type>或HTTP狀態碼<error-code>聲明錯誤頁面。
聲明一個“普通”型錯誤頁面。
這樣就為整個Web應用中所有部分設置了默認的錯誤頁面。
當要為單個JSP設置一個特定的錯誤頁面,在該JSP的page指令的errorPage屬性覆蓋這個設置即可。
為更明確的一個異常聲明錯誤頁面。
根據一個HTTP狀態碼聲明錯誤頁面
當一個頁面聲明為錯誤頁面時,該頁面立即得到一個其他頁面沒有的對象:exception
自己能通過程序生成錯誤碼嗎?
可以!!!調用HttpServletResponse的sendError方法,它會告訴容器生成錯我,就好像是容器自己生成的一樣。如果已經根據這個錯誤碼配置了一個要發送給客戶端的錯誤頁面,客戶就會得到這個錯誤頁面。錯誤碼也成為狀態碼,他們指的是同一個東西。
11 JSP的異常捕捉<c:catch>相當于try塊(注意沒有catch塊)<c:catch>標簽有如下屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
var | 用來儲存錯誤信息的變量 | 否 | None |
應該將有風險的EL或標記調用(或其他部分)包在的<c:catch>體中。異常就會在這里被捕獲。一旦有異常發生,控制就會跳至<c:catch>標記體的后面。
在<c:catch>標記結束后訪問異常該怎么辦?
正確的做法是:
<c:forTokens>標簽與<c:forEach>標簽有相似的屬性,不過<c:forTokens>還有另一個屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
delims | 分隔符 | 是 | 無 |
c:redirect標簽有如下屬性:
屬性 | 描述 | 是否必要 | 默認值 |
---|---|---|---|
url | 目標URL | 是 | 無 |
context | 緊接著一個本地網絡應用程序的名稱 | 否 | 當前應用程序 |
<c:redirect url="http://www.w3cschool.cc"/>14 理解TLD
TLD描述了兩個主要的內容:定制標記和EL函數。EL函數我們在EL中已經講過了。
怎么知道屬性的類型呢?
<attribute>有一個可選屬性,<type>它取一個完全限定類名作為類型。
標記體<body-content>里面能放什么內容呢?
可以放4種內容:
①empty:這個標記不能有體。
②scriptless:這個 標記不能有腳本元素,但可以是模板文本和EL,還可以是定制和標準動作。
③tagdependent:標記體要看作是純文本,所以不會計算EL,也不會觸發標記/動作。
④JSP:能在放在JSP中的東西都能放在這里。
對于<body-content>內容為empty,我們怎么調用標記?有3種方法:
①標記以斜線"/"結尾,省略結束標記。
②在開始標記和結束標記之間不要放任何內容。
③在開始標記和結束標記之間放<jsp:attribute>標記
容器在那些地方查找TLD呢?在4個位置查找:
15 實現一個定制標記處理器①直接在WEB-INF目錄中查找。
②直接在WEB-INF的一個子目錄中查找
③在WEB-INF/lib下一個JAR文件中的META-INF中查找。
④在WEB-INF/lib下一個JAR文件中的META-INF目錄中的子目錄中查找。
首先我們建立一個TLD,設置我們自定義的標簽:
1 <?xml version="1.0" encoding="ISO-8859-1"?> 2 <!DOCTYPE taglib 3 PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" 4 "http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd"> 5 <taglib> 6 <tlib-version>1.0</tlib-version> 7 <jsp-version>1.2</jsp-version> 8 <short-name>RandomTags</short-name> 9 <uri>randomThings</uri>10 <description>11 A simple tab library for the examples12 </description>13 <tag>14 <name>advice</name>15 <tag-class>jstl.AdvisorTagHandler</tag-class>16 <body-content>empty</body-content>17 <description>18 random advice19 </description>20 <attribute>21 <name>user</name>22 <required>true</required>23 <rtexprvalue>true</rtexprvalue>24 </attribute>25 </tag>26 </taglib>View Code
完成工作的Java類:
注意:再采用EL函數時,要創建一個有公共靜態方法的Java類,并且該方法的名字可以自己取,再在TLD中映射即可,但是在利用定制標記是,該方法名不能自定義,只能是doTag。
判斷是否為空或是否為null
16. JSTL 判斷對象是否為空<C:IF 判斷對象或集合是否為空判斷集合和對象是否為空:
list為集合,user為對象名
1 <c:if test="${empty user}">無user信息!TODO...</c:if>為空2 <c:if test="${!empty list}">list集合不為空判斷,TODO...</c:if>非空View Code<S:IF 判斷對象是否為空
1 <s:if test="null==user||user.isEmpty()">2 集合為空3 </s:if><s:else>4 集合不為空5 </s:else>View Code
或者
1 <s:if test="null!=user&&!user.isEmpty()">2 集合不為空3 </s:if>View Code
新聞熱點
疑難解答