1. 自定義標簽
由於在JSP頁面中直接嵌入Java代碼會導致頁面開起來非常混亂,不方便和美工等配合工作,為此,JSP提供了自定義標簽技術,可以代替直接嵌入Java代碼的方式提供動態邏輯,但自定義標簽本質上仍然是Java代碼
1.1. JSTL
JSTL(JavaServer Pages Standard Tag Library),JSP標准標簽庫,是一組JSP自定義標簽。這些標簽原本由第三方開發實現,由於效果質量非常好,sun公司就把這些標簽作為標准標簽打包成庫並加以推廣
現在先學習JSTL中主要自定義標簽的用法,后面再學習如何定義自己的自定義標簽
JSTL按照標簽功能分為多個庫,主要有:
| 標簽庫 |
uri |
建議前綴 |
| 核心標簽庫 |
http://java.sun.com/jsp/jstl/core |
c |
| 格式化標簽庫 |
http://java.sun.com/jsp/jstl/fmt |
fmt |
| 函數庫 |
http://java.sun.com/jsp/jstl/functions |
fn |
1.1.1. 核心標簽庫
主要包含<c:out>、<c:if>、<c:forEach>標簽,要想在JSP頁面中使用這些標簽,需要使用<%@ taglib >指令引入核心標簽庫的配置文件(tld文件在對應jar包的META-INF下面)
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> |
指定taglib時需要引入帶jsp的uri,這套是新版本(舊版本有時候不好用)

<c:out>
先把EL表達式計算結果中的特殊字符比如<、& 轉換為對應的實體字符,再輸出到HTML格式的響應中
JSP頁面中
| <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:out value="${ '<hello>' }" ></c:out> |
對應JSP生成的Servlet中主要的java代碼
| OutTag outTag = tagHandlerPool.get(OutTag.class); outTag.setValue(PageContextImpl.proprietaryEvaluate("${ '<hello>' }", Object.class, pageContext, null)); outTag.doStartTag(); |
每個自定義標簽都對應一個標簽類,比如<c:out>對應OutTag,在JSP頁面中每使用一次標簽,就會執行一次對應標簽對象的doStartTag()方法
和EL一樣,自定義標簽也是在服務器端執行的,客戶端也看不到自定義標簽,普通HTML注釋對自定義標簽也是無效的...
瀏覽器源代碼
| <hello> |
<c:if>
相當於Java中的if語句,當EL表達式的值為true時,就會執行其標簽體內容,也就是說會把標簽體內容加入到HTML格式的響應中。如果為false,就會跳過標簽體內容
| <c:if test="${ param.age<18 }"> 禁 </c:if> |
<c:forEach>
可以實現普通for循環和增強for循環兩種效果
普通for循環效果
| <c:forEach var="i" begin="0" step="1" end="5"> <c:out value="${ i }"></c:out> <br/> </c:forEach> |
var指定循環變量,每次循環開始時,內部都會調用pageContext.setAttribute("i", value),所以循環時可以使用EL表達式取出i當前的值。整個循環結束后,內部會調用pageContext.removeAttribute("i") 清理數據
begin指定循環變量的開始值
step指定循環變量的自增量,也稱為步長,默認為1
end指定循環變量的結束值,其實循環條件是i <= end
需要注意以上屬性都不支持EL表達式
增強for循環效果用來變量集合、數組
| <c:forEach items="${ requestScope.userList }" var="user"> <c:out value="${ user.name }"></c:out> <br/> </c:forEach> |
items指定待遍歷的集合或者數組,必須使用EL表達式
1.1.2. 格式化標簽庫
提供了<fmt:formatDate>標簽用來在JSP頁面中把Date對象轉換為指定格式的字符串,並輸出到HTML格式的響應中
| <fmt:formatDate value="${ requestScope.user.birthday }" pattern="yyyy-MM-dd"/> |
1.1.3. 函數庫
函數庫中提供了很多可以在EL表達式中使用的函數,其實就是一些靜態方法,絕大部分都是操作字符串的,比如fn:length、fn:contains、fn:toLowerCase、fn:toUpperCase、fn:trim、fn:split、fn:join、fn:indexOf、fn:replace、fn:startsWith、fn:endWith、fn:substring
| ${ fn:length('hello') } ${ fn:contains('hello','el') } |
1.2. 定義自己的自定義標簽
定義並使用自己的標簽分為三個步驟:
1 編寫自定義標簽類
2 在.tld文件中標簽類
3 在JSP頁面中引入tld文件后便可使用自定義標簽
下面以模仿<c:if test=””>為例說明
1 MyIfTag.java
| public class MyIfTag extends SimpleTagSupport {
private Boolean test; //對應標簽的test屬性
@Override public void doTag() throws JspException, IOException { if (test != null && test) { Writer writer = getJspContext().getOut(); JspFragment tagBody = getJspBody(); tagBody.invoke(writer); } } public Boolean getTest() { return test; } public void setTest(Boolean test) { this.test = test; } } |
標簽中需要用到到屬性,需要對應標簽類中的字段,並為字段提交get/set方法
如果標簽中有default屬性,由於default在Java中是關鍵字,可以使用_default變量名,並提供setDefault()方法給_default賦值
JspFragment表示標簽體內容,標簽體內容可能為空,也可能包含其他標簽,也可能嵌入Java代碼,其invoke(writer)方法會執行標簽體內容,並使用指定writer把執行結果輸出到響應中
這里並沒有出現前面說的doStartTag()方法,原因是doStartTag()屬於早期標簽類實現方式,有些復雜。這里使用的是簡易的實現方式,即繼承SimpleTagSupport
2 mytag.tld
| <?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1">
<tlib-version>1</tlib-version> <!-- 標簽庫內部版本號 --> <short-name>my</short-name> <!-- 建議前綴 --> <uri>/my-tag</uri> <!-- 標簽庫uri -->
<tag> <!-- 用來定義標簽 --> <name>if</name> <!-- 標簽名稱 --> <tag-class>com.rupeng.web.tag.MyIfTag</tag-class> <!-- 標簽類 --> <body-content>scriptless</body-content> <!-- 表示標簽體中不可嵌入Java代碼 --> <attribute> <!-- 用來定義標簽屬性 --> <name>test</name> <!-- 屬性名稱 --> <required>true</required> <!-- 屬性是否必須 --> <rtexprvalue>true</rtexprvalue> <!-- 屬性是否支持EL表達式 --> </attribute> </tag> </taglib> |
<body-content>用來指定標簽體內容類型,取值如下:
| empty |
標簽體為空 |
| scriptless |
標簽體中不可嵌入Java代碼,其他無限制 |
| JSP |
標簽體內容不做限制(當前JSP版本已廢棄此選項) |
3 JSP頁面中
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib uri="/my-tag" prefix="my" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>自定義標簽</title> </head> <body> <my:if test="${ param.age<18 }">禁</my:if> </body> </html> |
