JSP自定義標籤的實現

一、自定義標籤概述

自定義標籤是用戶定義的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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章