javascript
Head First JSP---随笔七
強大的定制標記(JSTL)
有時只是EL或標準動作還不夠。如果我們想循環處理一個數組中的數據,并在一個HTML表中每一行顯示一項,該怎么做?這時,就需要強大的JSTL了。
使用標記庫建立JSP頁面
9.1 描述“taglib”指令的語法和語義:包括標準標記庫的相應“taglib”指令和標記文件的相應“taglib”指令。
9.2 創建定制標記結構來支持給定的設計目標。
9.3 對于以下JSP標準標記庫(JSTL v1.1)標記,明確這些標記的語法,并描述標記的動作語義
1. 核心標記:out,set,remove和catch
2. 條件標記:if,choose,when和otherwise
3. 循環標記:forEach
4. URL相關的標記:url
安裝JSTL 1.1
使用c:out標記
可以顯式地聲明轉換XML實體:<c:out value="${perfix.name} escapeXml="true"/>,則說明將EL表達式的HTML按文本顯示。
可以顯式地聲明不轉換XML實體:<c:out value="${perfix.name}" escapeXml="false"/>,則說明將EL表達式所獲取到的HTML標記都進行計算,不按文本顯示(例如:EL獲得到的字符串是<br/><br/>,則將計算出2個換行)。
HTML需要轉換的特殊字符:
這里指出:escapeXml默認為true。
跨網站攻擊(cross-site hacking)或跨網站腳本攻擊(cross-site scripting)
這種攻擊是指一個用于使用你的Web應用作為傳輸機制向另一個用戶的web瀏覽器發動攻擊。
如圖:
default屬性設置一個默認值
假設我們在EL表達式計算為null的時候希望打印出一個默認值。
有兩種做法:
(1)<c:out>單標簽提供一個default屬性,是<c:out value="${user}" default="guest"/>這樣的形式。
(2)<c:out>雙標簽可以這樣做:<c:out value="${user}">guest</c:out>。
不用腳本(scriptlet)循環的c:forEach標記
注意:元素和數組。
c:forEach剖析
<c:forEach>標記可以循環數組和集合中的每一個元素:(如下)
還有一個循環計數器(varStatus):
記住還需要count。
嵌套c:forEach標記
注意嵌套時的屬性值。
JSTL注意的幾點
1.問:你怎么知道”varStatus”屬性是這樣一個類的實例,你是怎么知道它有一個”count”性質的?
答:JSTL 1.1規范告訴我的。
2.問:能改變迭代的步長嗎?例如i+=3?
答:可以的,JSTL 1.1中有這些問題的答案,改變步長可以使用step屬性。
3.一個需要注意的地方:作用域!
c:if條件包含
所有人都得到同樣的頁面,但是成員在頁面上能“看到”更多東西。
這里指出:并沒有一個“else”的字句。
c:choose標記
c:set標記的var
“var”版本用于設置屬性變量(pageScope,requestScope,applicationScope,session)。
這里指出:var必須是一個直接量,不能使EL表達式!
c:set標記的target
“target”版本用于設置對象性質(bean,Map)
c:set的要點和技巧
c:remove標記
c:import標記
<c:import>標記讓我們只要知道url就可以把別人的頁面當做自己頁面的一部分(注意最后一行)。
c:param標記
與<jsp:param>類似。
c:url可以滿足所有超鏈接需求
如果客戶瀏覽器不支持cookie,我們就需要url重寫。
這樣方便多了。
如果URL需要編碼
建立自己的錯誤頁面
在DD中配置錯誤頁面
如果像上面那樣寫的話,需要在所有的JSP文件中寫上指定的錯誤頁面,豈不是要累死?
這個時候DD中允許你配置錯誤頁面,對所有的JSP而言。
在DD中可以根據<exception-type>或狀態碼<error-code>聲明錯誤頁面。
錯誤頁面得到一個exception的對象
這樣,對我們頁面排錯就有了可靠的工具。
c:catch來恢復頁面,就像try/catch一樣
一個<c:catch>會同時作為try和catch部分,這聽上去有點怪,確實沒有單獨的try標記。我們要把有風險的EL或標記調用(或其他部分)包在<c:catch>的體中,異常就會在這里被捕獲。不過,不能把它當成一個catch塊,因為一旦異常發生,控制就會跳至<c:catch>標記體的最后。
可以將異常設置為一個屬性
對于Web應用錯誤處理,只有正式指定錯誤頁面(isErrorPage=true)才能得到異常對象。
如果想要在<c:catch>標記結束后訪問異常,可以使用可選的var屬性。
c:catch注意
JSTL的標記庫
JSTL相當龐大。1.1版本有5個庫,其中4個是定制標記庫,還有一個提供了大量用于串處理的函數。
使用非JSTL的標記庫
創建標記的支持代碼并不輕松(支持代碼就是在JSP中放入標記時所需要調用的Java代碼)。
要使用定制庫,必須閱讀TLD。我們想知道的一切都在這里。
理解TLD
可以看出每個標記都對應著一個name和一個類和體中能否為空,并且可以設置它的屬性以及這個屬性能否是一個表達式。
使用定制“advice”標記
“advice”標記時一個簡單的標記,它有一個屬性(用戶名),并打印一個隨機的建議。這非常簡單,使用一個普通的EL函數(有一個靜態方法 getAdvice(String name))就完全可以做到,但我們還是把它做成一個簡單的標記。
定制標記處理器
這個簡單的標記處理器拓展了SimpleTagSupport,而且實現了兩個關鍵方法:doTag()和setUser,doTag()是完成具體工作的方法,setUser()方法接收屬性值。
可以知道如果利用定制標記,方法名就必須是doTag()。也就是說,一個標記對應一個類。
注意rtexprvalue
如果<rtexprvalue>為false,或者未定義<rtexprvalue>,那么屬性值只能是一個String直接量。
還需要注意屬性類型:
rtexprvalue不只是針對EL表達式
可以使用3種表達式:
標記體能放什么?
首先看看TLD中標記配置<body-content>能放什么
對于沒有體的標記,有3種調用方法
標記處理器、TLD和JSP
標記處理器開發人員要創建TLD,告訴容器和JSP開發人員如何使用這個標記。JSP開發人員并不關心TLD的<tag-class>元素;這是容器要考慮的事情。JSP開發人員主要關心uri、標記名和標記語法。標記能有體嗎?屬性必須是一個String直接量嗎?屬性能使一個表達式嗎?這個屬性是可選的嗎?表達式要計算為何種類型?
要部署和運行一個使用了標記的Web應用,只需要這3部分——標記處理器類、TLD和JSP。
taglib的uri屬性只是一個名,而不是一個位置
TLD中的<uri>要與taglib指令中的uri匹配!
容器建立一個映射
在JSP 2.0之前,開發人員必須為TLD中的<uri>與TLD文件的具體位置之前指定一個映射。例如一個JSP頁面有<%@ taglib prefix="mine" uri="randomThings"%>,則部署描述文件(web.xml)必須告訴容器到哪里找有匹配的TLD文件,如下:
在JSP 2.0出現后,DD中已經沒有<taglib>標簽了!所以,容器會自動建立TLD和<uri>名之間的映射。
這是怎么做到的?答案是:在能放TLD的所有特定位置上找一遍。部署一個Web應用時,只要把TLD放在容器會搜索位置上,容器就會發現這個TLD,并為標記庫建立一個映射。
容器會在4個位置查找TLD
如果JSP使用了多個標記庫
要記住幾點:
本章完
因為感冒,所以看這章的時候有點累。。不過加油!!
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Head First JSP---随笔七的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 互联网日报 | 2月23日 星期二 |
- 下一篇: gradle idea java ssm