使用標簽可以替換 jsp 頁面上的腳本,讓頁面更加簡潔,維護更加方便,增加程序安全性。
在 javaee api 中有一個接口 javax.servlet.jsp.tagext.JspTag , 它是所有的標簽的根接口。
在 jsp2.0 以后,定義了一個更加簡單的 javax.servlet.jsp.tagext.SimpleTag,這個接口就描述了如何自定義標簽。
標簽的分類:
- 傳統標簽
- 簡單標簽 SimpleTag
SimpleTag 體系
SimpleTag 有一個實現類 SimpleTagSupport ,自定義標簽類一般會繼承它。
定義一個標簽的步驟:
- 定義一個標簽類讓它實現 SimpleTag 接口或繼承 SimpleTagSupport 類
- 做一個標簽的描述文件 .tld 文件,在這個文件中來對標簽進行描述
- 在 jsp 頁面上使用自定義標簽。
關於 SimpleTag 接口的方法描述
- doTag 方法它的作用:描述標簽的功能 (會被自動調用)
- setJspContext : 它的參數是JspContext,它的作用是將頁面的pageContext對象傳遞到標簽類中。(很大用途,用於獲取其他八大對象)
- setJspBody : 將標簽體的內容緩存到內存對象中,而參數JspFragment 相當於標簽體內容。
- getParent setParent 將標簽的父標簽引入。(基本不用)
下面是一個自定義標簽類:(是一個多次打印標簽體內容的 java 類)
package online.mytag; import java.io.IOException; import java.io.StringWriter; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; public class PrintTag extends SimpleTagSupport { private int count; public int getCount() { return count; } public void setCount(int count) { this.count = count; } @Override public void doTag() throws JspException, IOException { //創建一個流,用於接收標簽體的內容 StringWriter sw = new StringWriter(); getJspBody().invoke(sw); String str = sw.toString(); JspWriter out = getJspContext().getOut(); for (int i = 0; i < count; i++) { out.write(str); } } }
下面是一個自定義標簽類:(用於獲取瀏覽器端的 ip 地址)
package online.mytag; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.SimpleTagSupport; public class IpTag extends SimpleTagSupport { /** * 向瀏覽器輸出瀏覽器的ip */ @Override public void doTag() throws JspException, IOException { String ip = (String)((PageContext)(getJspContext())).getRequest().getRemoteAddr(); getJspContext().getOut().write(ip); } }
上面兩個標簽實現類對應的 .tld 文件:
<?xml version="1.0" encoding="UTF-8"?> <taglib version="2.1" 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"> <tlib-version>1.0</tlib-version> <short-name>my</short-name> <!-- 這里是使用該標簽時taglib的refer屬性值:<%@taglib uri="online.mytag.IpTag" prefix="my"%> --> <uri>http://java.sun.com/jsp/jstl/mytag</uri> <!-- 這里是使用該標簽時taglib的uri屬性 --> <tag> <!-- 這里的每一個<tag>都指定一個標簽java類 --> <description>輸出瀏覽器端的ip</description> <!-- 一些描述,也就是注釋 --> <name>getIp</name> <!-- 使用該標簽類時的標簽名 --> <tag-class>online.mytag.IpTag</tag-class> <!-- 標簽類的全類名 --> <body-content>empty</body-content> <!-- 這個屬性說明是否有標簽體 --> </tag> <tag> <description>根據標簽屬性值循環輸出標簽體</description> <name>print</name> <tag-class>online.mytag.PrintTag</tag-class> <body-content>scriptless</body-content> <attribute> <!-- 指的是標簽類中的字段,有幾個字段,就有幾個attribute標簽 --> <description>循環的次數</description> <name>count</name> <!-- 使用該標簽時,標簽中的屬性名 --> <required>true</required> <!-- 指明該屬性是否是必需的 --> <rtexprvalue>true</rtexprvalue> <!-- 指明該屬性是否支持el表達式 --> </attribute> </tag> </taglib>
在 jsp 頁面中使用自定義標簽:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@taglib uri="online.mytag.IpTag" prefix="my"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <my:getIp/> <my:print count="2"> hello tag </my:print> </body> </html>
畫個圖說明下 tag 標簽下的子標簽:(注意: attribute 對應的字段必須在標簽類中提供對應的 get/set 方法)
總結下自定義標簽:
我們使用的是簡單標簽,也就是通過實現 SimpleTag 或繼承 SimpleTagSupport 來實現自定義標簽。
基本步驟:
1.創建標簽類 implements SimpleTag extends SimpleTagSupport類
- JspContext 它就代表的是jsp頁面上的pageContext對象
- JspFragment 它就代表的是標簽體中的內容,通過它的 invoke() 方法可以將標簽體的內容指定到 invoke() 方法參數的輸出流輸出,如果為 null ,默認是當前 jsp 頁面關聯的 out 對象。
2.在WEB-INF/創建一個 .tld 文件
- 使用 <tag> 來描述標簽
- 使用 <tag> 下的 <name> 來定義標簽名稱
- 使用 <tag> 下的 <tag-class> 來定義標簽類的
- 使用 <tag> 下的 <body-content> 來描述標簽體中是否有內容,可以使用的值有兩個 :empty scriptless
- 使用 <tag> 下的 <attribute> 來描述屬性,但是必須在標簽類中提供對應的get/set方法
- 使用 <attribute> 下的 <name> 來聲明屬性名稱
- 使用 <attribute> 下的 <required> 來聲明屬性是否必須存在
- 使用 <attribute> 下的 <rtexprvalue> 來聲明屬性是否可以使用el表達式
注意:
- 在 .tld 文件創建時,要選擇 2.0 以上版本,並且 .tld 文件創建后有缺陷,需要手動將 schemaLocation 中第一個值復制一份放到 xsd 文件前
(xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd")
3.在 jsp 頁面上使用 taglib 導入標簽
- 使用標簽必須使用 taglib 先導入標簽才能用。