自定义标签

第一建立一个java类:

public class HelloWorldTag extends SimpleTagSupport
{
    //重写doTag方法,该方法在标签结束生成页面内容
    public void doTag()throws JspException,
        IOException
    {
        //获取页面输出流,并输出字符串
        getJspContext().getOut().write("Hello World "
            + new java.util.Date());
    }
}

2.建立TLD(Tag Library Definition)文件:

<?xml version="1.0" encoding="GBK"?>

<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 web-jsptaglibrary_2_0.xsd"
    version="2.0">
    <tlib-version>1.0</tlib-version>
    <short-name>mytaglib</short-name>
    <!-- 定义该标签库的URI -->
    <uri>/mytaglib</uri>

    <!-- 定义第一个标签 -->
    <tag>
        <!-- 定义标签名 -->
        <name>helloWorld</name>
        <!-- 定义标签处理类 -->
        <tag-class>lee.HelloWorldTag</tag-class>
        <!-- 定义标签体为空 -->
        <body-content>empty</body-content>
    </tag>
  </taglib>

标签库的使用:

第一:前提条件:
1.标签库URI:确定使用那个标签库。

2标签名:确定使用那个标签。

步骤:

1导入标签库

<%@ taglib uri="tagliburi" prefix="tagPrefix"%>

2在jsp页面中使用标签

<tagPrefix:tagName tagAttribute="tagValue" ...>
<tagBody/>
</tagPrefix:tagName>

实例:根据上文建立的tld,编写如下jsp页面

<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<!-- 导入标签库,指定mytag前缀的标签,由http://www.crazyit.org/mytaglib的标签库处理 -->
<%@ taglib uri="/mytaglib" prefix="mytag"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>自定义标签示范</title>
    <meta name="website" content="http://www.crazyit.org" />
</head>
<body bgcolor="#ffffc0">
<h2>下面显示的是自定义标签中的内容</h2>
<!-- 使用标签 ,其中mytag是标签前缀,根据taglib的编译指令,
mytag前缀将由http://www.crazyit.org/mytaglib的标签库处理 -->
<mytag:helloWorld/><br/>
</body>
</html>

还要加上一步:

在web.xml文件中添加引入代码:

    <jsp-config>
        <taglib>
            <taglib-uri>/mytaglib</taglib-uri>
            <taglib-location>/WEB-INF/mytaglib.tld</taglib-location>
        </taglib>
    </jsp-config>

带属性的标签:

<!-- 定义第二个标签 -->
    <tag>
        <!-- 定义标签名 -->
        <name>query</name>
        <!-- 定义标签处理类 -->
        <tag-class>lee.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>
            <fragment>true</fragment>
        </attribute>
        <!-- 配置标签属性:pass -->
        <attribute>
            <name>pass</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
        <!-- 配置标签属性:sql -->
        <attribute>
            <name>sql</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
    </tag>

java代码清单:

public class QueryTag extends SimpleTagSupport
{
    //标签的属性
     
private String driver;
    private String url;
    private String user;
    private String pass;
    private String sql;

    //setter和getter方法省略
    //执行数据库访问的对象 
    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);
            //获取数据库连接
            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' bgColor='#9999cc' width='400'>");
            //遍历结果集
            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>");
            }
        }
        catch(ClassNotFoundException cnfe)
        {
            cnfe.printStackTrace();
            throw new JspException("自定义标签错误" + cnfe.getMessage());
        }
        catch (SQLException ex)
        {
            ex.printStackTrace();
            throw new JspException("自定义标签错误" + ex.getMessage());
        }
        finally
        {
            //关闭结果集
            try
            {
                if (rs != null)
                    rs.close();
                if (stmt != null)
                    stmt.close();
                if (conn != null)
                    conn.close();
            }
            catch (SQLException sqle)
            {
                sqle.printStackTrace();
            }
        }
    }
}

带标签体的标签:

tld内容:

    <!-- 定义第三个标签 -->
    <tag>
        <!-- 定义标签名 -->
        <name>iterator</name>
        <!-- 定义标签处理类 -->
        <tag-class>lee.IteratorTag</tag-class>
        <!-- 定义标签体不允许出现JSP脚本 -->
        <body-content>scriptless</body-content>
        <!-- 配置标签属性:collection -->
        <attribute>
            <name>collection</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
        <!-- 配置标签属性:item -->
        <attribute>
            <name>item</name> 
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
    </tag>
package org.sh.com.tag;

import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.*;
import java.util.*;

public class IteratorTag extends SimpleTagSupport {
    // 标签属性,用于指定需要被迭代的集合
    private String collection;
    // 标签属性,指定迭代集合元素,为集合元素指定的名称
    private String item;

    // collection属性的setter和getter方法
    public void setCollection(String collection) {
        this.collection = collection;
    }

    public String getCollection() {
        return this.collection;
    }

    // item属性的setter和getter方法
    public void setItem(String item) {
        this.item = item;
    }

    public String getItem() {
        return this.item;
    }

    // 标签的处理方法,简单标签处理类只需要重写doTag方法
    public void doTag() throws JspException, IOException {
        // 从page scope中获取属性名为collection的集合
        Collection itemList = (Collection) getJspContext().getAttribute(
                collection);
        // 遍历集合
        for (Object s : itemList) {
            // 将集合的元素设置到page 范围
            getJspContext().setAttribute(item, s);
            // 输出标签体
            getJspBody().invoke(null);
        }
    }
}
jsp页面:
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ page import="java.util.*"%>
<!-- 导入标签库,指定mytag前缀的标签,
由http://www.crazyit.org/mytaglib的标签库处理 -->
<%@ taglib uri="/mytaglib" prefix="mytag"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title> 带标签体的标签-迭代器标签 </title>
    <meta name="website" content="http://www.crazyit.org" />
</head>
<body>
    <h2>带标签体的标签-迭代器标签</h2><hr/>
    <%
    //创建一个List对象
    List<String> a = new ArrayList<String>();
    a.add("疯狂Java");
    a.add("www.crazyit.org");
    a.add("java");
    //将List对象放入page范围内
    pageContext.setAttribute("a" , a);
    %>
    <table border="1" bgcolor="#aaaadd" width="300">
        <!-- 使用迭代器标签,对a集合进行迭代 -->
        <mytag:iterator collection="a" item="item">
        <tr>
            <td>${pageScope.item}</td>
        <tr>
        </mytag:iterator>
    </table>
</body>
</html>

以页面片段作为属性的标签:

tld文件:

    <tag>
        <!-- 定义标签名 -->
        <name>fragment</name>
        <!-- 定义标签处理类 -->
        <tag-class>lee.FragmentTag</tag-class>
        <!-- 指定该标签不支持标签体 -->
        <body-content>scriptless</body-content>
        <!-- 定义标签属性:fragment -->
        <attribute>
            <name>fragment</name>
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
    </tag>

java文件:

public class FragmentTag extends SimpleTagSupport 
{
    private JspFragment fragment;
    
    //fragment属性的setter和getter方法
    public void setFragment(JspFragment fragment)
    {
        this.fragment = fragment;
    }
    public JspFragment getFragment()
    {
        return this.fragment;
    }
    @Override
    public void doTag() throws JspException, IOException
    {
        JspWriter out = getJspContext().getOut();
        out.println("<div style='padding:10px;border:1px solid black'>");
        out.println("<h3>下面是动态传入的JSP片段</h3>");
        //调用、输出“页面片段”
        fragment.invoke( null );
        out.println("</div");
    }
}

jsp文件:

<%@ page contentType="text/html; charset=GBK" language="java"
    errorPage=""%>
<!-- 导入标签库,指定mytag前缀的标签,
    由http://www.crazyit.org/mytaglib的标签库处理 -->
<%@ taglib uri="/mytaglib" prefix="mytag"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>自定义标签示范</title>
<meta name="website" content="http://www.crazyit.org" />
</head>
<body bgcolor="#ffffc0">
    <h2>下面显示的是自定义标签中的内容</h2>
    <mytag:fragment>
        <jsp:attribute name="fragment">
            <mytag:helloWorld />
        </jsp:attribute>
    </mytag:fragment>
    <br />
    <mytag:fragment>
        <jsp:attribute name="fragment">
            ${pageContext.request.remoteAddr}
        </jsp:attribute>
    </mytag:fragment>
</body>
</html>
注意:如果在<mytag:fragment> 里面加上注释会出现“According to TLD, tag mytag:fragment must be empty, but is not”错误,

把<mytag:fragment> 开始标签
与</mytag:fragment>结束标签之间的注释全部去掉——HTML注释、JSP注释都要去掉。
——最新版本的Tomcat不允许此处出现注释

动态属性的标签:

动态属性的标签比普通标签多了如下两个额外的要求:

-->标签处理累还需要实现DynamivAttributes接口。

-->配置标签是通过<dynamic-attributes…/>子元素制定该标签支持动态属性

下面一个例子:

java代码:

public class DynaAttributesTag 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>");
    }

    @Override
    public void setDynamicAttribute(String uri, String localName, Object value)
            throws JspException {
        // 添加属性名
        keys.add(localName);
        // 添加属性值
        values.add(value);
    }
}

TLD代码:

    <!-- 定义接受动态属性的标签 -->
    <tag>
        <name>dynaAttr</name>
        <tag-class>org.sh.com.tag.DynaAttributesTag</tag-class>
        <body-content>empty</body-content>
        <!-- 指定支持动态属性 -->
        <dynamic-attributes>true</dynamic-attributes>
    </tag>

JSP代码:
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<!-- 导入标签库,指定mytag前缀的标签,
    由http://www.crazyit.org/mytaglib的标签库处理 -->
<%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>自定义标签示范</title>
    <meta name="website" content="http://www.crazyit.org" />
</head>
<body bgcolor="#ffffc0">
<h2>下面显示的是自定义标签中的内容</h2>
<h4>指定两个属性</h4>
<mytag:dynaAttr name="crazyit" url="crazyit.org"/><br/>
<h4>指定四个属性</h4>
<mytag:dynaAttr 书名="疯狂Java讲义" 价格="99.0"
    出版时间="2008年" 描述="Java图书"/><br/>
</body>
</html>


另注:body-content取值的意义 转自:http://blog.csdn.net/aaa1117a8w5s6d/article/details/8157212

body-content的值有下面4种:

<xsd:enumeration value="tagdependent"/>

 <xsd:enumeration value="JSP"/>

 <xsd:enumeration value="empty"/>

 <xsd:enumeration value="scriptless"/>

tagdependent:标签体内容直接被写入BodyContent,由自定义标签类来进行处理,而不被JSP容器解释,

如下:

<test:myList>

select name,age from users

</test:myList>

JSP:接受所有JSP语法,如定制的或内部的tag、scripts、静态HTML、脚本元素、JSP指令和动作。如:

<my:test>

 <%=request.getProtocol()%>  // ②

</my:test>

具体可参考后面附源码。

empty:空标记,即起始标记和结束标记之间没有内容。

下面几种写法都是有效的,

<test:mytag />

<test:mytag uname="Tom" />

<test:mytag></test:mytag>

scriptless:接受文本、EL和JSP动作。如上述使用<body-content> scriptless </body-content>则报错,具体可参考后面附源码。

原文地址:https://www.cnblogs.com/sunhan/p/3800826.html