一、自定義標籤概述
自定義標籤是用戶定義的JSP語言元素。當JSP頁面包含一個自定義標籤時將被轉化爲servlet,標籤轉化爲對被 稱爲tag handler的對象的操作,即當servlet執行時Web container調用那些操作。JSP標籤擴展可以讓你創建新的標籤並且可以直接插入到一個JSP頁面。 JSP 2.0規範中引入Simple Tag Handlers來編寫這些自定義標記。下面分幾種情況概述:
簡單的自定義標籤
1、自定義標籤處理類
package mytaglib;
import java.io.IOException;
import java.util.Date;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/**
* 自定義標籤類都應該繼承一個父類,javax.servlet.jsp.tagext.SimpleTagSupport
* 1.如果標籤類包含屬性,每個屬性應該都有對應的getter和setter方法
* 2.重寫doTag()方法,這個方法負責生成頁面內容
* @author xieyongxue
*
*/
public class HelloWorldTag extends SimpleTagSupport{
//重寫doTag()方法,該方法爲標籤生成頁面內容
public void doTag()throws JspException,IOException
{
//獲取頁面輸出流,並輸出字符串
getJspContext().getOut().write("Hello World"+new Date());
}
}
2、建立TLD文件(該文件建立在WEB-INF下)
<?xml version="1.0" encoding="UTF-8" ?>
<taglib 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-jsptaglibrary_2_0.xsd"
version="2.0">
<description>A tag library exercising SimpleTag handlers.</description>
<!-- 定義該標籤實現的版本 -->
<tlib-version>1.0</tlib-version>
<!-- 該標籤的默認短名 -->
<short-name>mytaglib</short-name>
<!-- 定義該標籤庫的URI -->
<uri>http://www.crazyit.org/mytaglib</uri>
<!-- 定義第一個標籤 -->
<tag>
<description>Outputs Hello, World</description>
<!-- 定義標籤名 -->
<name>helloWorld</name>
<!-- 定義標籤的處理類 -->
<tag-class>mytaglib.HelloWorldTag</tag-class>
<!-- 定義標籤體爲空 -->
<body-content>empty</body-content>
</tag>
<!-- 定義有屬性的標籤 -->
<tag>
<!-- 定義標籤名 -->
<name>query</name>
<!-- 定義標籤處理類 -->
<tag-class>mytaglib.QueryTag</tag-class>
<!-- 定義標籤體爲空 -->
<body-content>empty</body-content>
<!-- 配置標籤的屬性:driver -->
<attribute>
<name>driver</name>
<!--設置該屬性是否爲必需屬性 -->
<required>true</required>
<fragment>true</fragment>
</attribute>
<!-- 配置標籤的屬性:url -->
<attribute>
<name>url</name>
<!--設置該屬性是否爲必需屬性 -->
<required>true</required>
<fragment>true</fragment>
</attribute>
<!-- 配置標籤的屬性:user -->
<attribute>
<name>user</name>
<!--設置該屬性是否爲必需屬性 -->
<required>true</required>
<!-- 設置該屬性是否是否支持JSP腳本,表達式等動態內容 -->
<fragment>true</fragment>
</attribute>
<!-- 配置標籤的屬性:pass -->
<attribute>
<name>pass</name>
<!--設置該屬性是否爲必需屬性 -->
<required>true</required>
<!-- 設置該屬性是否是否支持JSP腳本,表達式等動態內容 -->
<fragment>true</fragment>
</attribute>
<!-- 配置標籤的屬性:sql -->
<attribute>
<name>sql</name>
<!--設置該屬性是否爲必需屬性 -->
<required>true</required>
<!-- 設置該屬性是否是否支持JSP腳本,表達式等動態內容 -->
<fragment>true</fragment>
</attribute>
</tag>
<!-- 帶標籤體的標籤 -->
<tag>
<!-- 定義標籤名 -->
<name>iterator</name>
<!-- 該標籤的處理類 -->
<tag-class>mytaglib.IteratorTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>collection</name>
<!--設置該屬性是否爲必需屬性 -->
<required>true</required>
<!-- 設置該屬性是否是否支持JSP腳本,表達式等動態內容 -->
<fragment>true</fragment>
</attribute>
<attribute>
<name>item</name>
<!--設置該屬性是否爲必需屬性 -->
<required>true</required>
<!-- 設置該屬性是否是否支持JSP腳本,表達式等動態內容 -->
<fragment>true</fragment>
</attribute>
</tag>
<!--頁面片段作爲屬性的標籤 -->
<tag>
<name>fragment</name>
<tag-class>mytaglib.FragmentTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>fragment</name>
<!--設置該屬性是否爲必需屬性 -->
<required>true</required>
<!-- 設置該屬性是否是否支持JSP腳本,表達式等動態內容 -->
<fragment>true</fragment>
</attribute>
</tag>
<!--動態屬性標籤 -->
<tag>
<name>dynaAttr</name>
<tag-class>mytaglib.DynaAttributeTag</tag-class>
<body-content>empty</body-content>
<!-- 設定支持動態 -->
<dynamic-attributes>true</dynamic-attributes>
</tag>
</taglib>
3、測試JSP
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!-- 導出標籤庫,指定mytag前綴的標籤 -->
<%@taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>使用標籤</title>
</head>
<body>
<h1>下面顯示的自定義標籤的內容:</h1>
<mytag:helloWorld/>
<h1>下面顯示的自定義標籤內容(帶屬性):</h1>
<mytag:query
user="root"
url="jdbc:mysql://localhost:3306/escshop"
pass=""
driver="com.mysql.jdbc.Driver"
sql="select * from student"/>
<h1>下面顯示帶標籤體的自定義標籤</h1>
<%
List<String> list=new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
pageContext.setAttribute("list",list);
%>
<table>
<mytag:iterator item="item" collection="list">
<tr>
<td>${pageScope.item}</td>
</tr>
</mytag:iterator>
</table>
<h1> 動態屬性標籤</h1>
<div>
<mytag:dynaAttr url="jdbc:mysql://localhost:3306/escshop" name="xue"/>
</div>
<div>
<mytag:dynaAttr id="1" name="xue" url="jdbc:mysql://localhost:3306/escshop"/>
</div>
</body>
</html>
帶屬性的標籤(注:TLD文件與測試文件在上述例子)
package mytaglib;
import java.sql.Statement;
import java.io.IOException;
import java.io.Writer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class QueryTag extends SimpleTagSupport{
//定義成員變量來代表標籤的屬性
private String driver;
private String url;
private String user;
private String pass;
private String sql;
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
//執行數據庫的訪問對象
private Connection conn=null;
private Statement stmt=null;
private ResultSet rs=null;
private ResultSetMetaData rsmd=null;
//標籤顯示
public void doTag()throws JspException,IOException{
try {
//註冊驅動
Class.forName(driver);
try {
//數據庫連接
conn=DriverManager.getConnection(url,user,pass);
//創建statement對象
stmt=conn.createStatement();
//執行查詢
rs=stmt.executeQuery(sql);
rsmd=rs.getMetaData();
//獲取列條目
int columnCount=rsmd.getColumnCount();
//獲取頁面輸出流
Writer out=getJspContext().getOut();
out.write("<table border='1'>");
while (rs.next()) {
out.write("<tr>");
for (int i = 1; i <=columnCount; i++) {
out.write("<td>");
out.write(rs.getString(i));
out.write("</td>");
}
out.write("</tr>");
}
out.write("</table>");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("自定義標籤錯誤1:"+e.toString());
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("自定義標籤錯誤2:"+e.toString());
}
}
}
帶標籤體的標籤(注:TLD文件與測試文件在上述例子)
帶標籤體的標籤,可以在標籤體內嵌入其他標籤(如HTML,JSP等),通常用於完成一些邏輯運算,如判斷,循環等。
package mytaglib;
import java.io.IOException;
import java.util.Collection;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/**
* 帶標籤體的自定義標籤
* @author xieyongxue
*
*/
public class IteratorTag extends SimpleTagSupport{
//標籤屬性,用於被指定被迭代的集合
private String collection;
//標籤屬性,爲集合元素指定的名稱
private String item;
public void doTag()throws JspException,IOException{
//從page scope中獲取屬性值的集合
System.out.println(getJspContext().getAttribute(collection));
Collection itemList=(Collection)getJspContext().getAttribute(collection);
//遍歷集合
for (Object object : itemList) {
//將元素的值設置到page的範圍
getJspContext().setAttribute(item,object);
//輸出的標籤體
getJspBody().invoke(null);
}
}
public String getCollection() {
return collection;
}
public void setCollection(String collection) {
this.collection = collection;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
}
以頁面片段作爲屬性的標籤(TLD文件在上述例子文件)
JSP 2規範的自定義標籤還允許直接將一段”頁面片段”作爲屬性,這種方式給自定義標籤提供了更大的靈活性。以”頁面片段”爲屬性的標籤與普通標籤區別並不大,只有兩個簡單的改變:
標籤處理類中定義類型爲JspFragment的屬性,該屬性代表了”頁面片段”。
使用標籤庫時,通過動作指令爲標籤庫屬性指定值。
下面的程序定義了一個標籤處理類,該標籤處理類中定義了一個JspFragment類型的屬性,即表明該標籤允許使用”頁面片段”類型的屬性。
package mytaglib;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/*
* 頁面片段作爲屬性的標籤
*/
public class FragmentTag extends SimpleTagSupport{
private JspFragment fragment;
public JspFragment getFragment() {
return fragment;
}
public void setFragment(JspFragment fragment) {
this.fragment = fragment;
}
@Override
public void doTag()throws JspException,IOException{
JspWriter out=getJspContext().getOut();
out.println("<div style='width:600px;height=500px'>");
out.println("<h1>下面是動態加載進的JSP頁面</h1>");
//調用輸出JSP頁面、
fragment.invoke(null);
out.println("</div>");
}
}
測試JSP:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!-- 導出標籤庫,指定mytag前綴的標籤 -->
<%@taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>使用標籤</title>
</head>
<body>
<mytag:fragment>
<jsp:attribute name="fragment">
<mytag:helloWorld/>
</jsp:attribute>
</mytag:fragment>
</body>
</html>
動態屬性標籤(TLD文件與測試文件在上述文件)
當標籤傳入的屬性名與值的個數不確定時候,就依靠這個來,這也是和屬性標籤實現方式的區別。
package mytaglib;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.DynamicAttributes;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/**
* 動態屬性標籤
* @author xieyongxue
*
*/
public class DynaAttributeTag extends SimpleTagSupport implements DynamicAttributes{
//用於保存屬性名值
private ArrayList<String> keys=new ArrayList<String>();
//用於保存屬性值的值
private ArrayList<Object> values=new ArrayList<Object>();
@Override
public void doTag()throws JspException,IOException{
JspWriter out=getJspContext().getOut();
//此處只打印屬性名值
out.println("<ol>");
for (int i = 0; i<keys.size(); i++) {
String key=keys.get(i);
Object value=values.get(i);
out.println("<li>"+key+"="+value+"</li>");
}
out.println("</ol>");
}
public void setDynamicAttribute(String uri, String localName, Object value)
throws JspException {
// TODO Auto-generated method stub
keys.add(localName);
values.add(value);
}
}