http://blog.youkuaiyun.com/u010819416/article/details/43318029
一种可在页面中使用的标签,这种标具有和HTML标签类似的语法,但又可以完成JSP脚本的功能——这种标签就是JSP自定义标签。
开发标签库的步骤:
1、开发自定义标签处理类;
2、建立一个*.tld文件,每个*.tld文件对应一个标签库,每个标签库可包含多个标签;
3、在jsp文件中使用自定义标签。
2.11.1 开发自定义标签类
*自定义标签类应该继承一个父类:java.servlet.jsp.tagext.SimpleTagSupport;
*如果标签类包含属性,每个属性都有对应的getter和setter方法;
*重写doTag()方法,这个方法负责生产页面内容
例子:
在页面上输出HelloWord的标签:HelloWorldTag.java
- package lee;
- import javax.servlet.jsp.tagext.*;
- import javax.servlet.jsp.*;
- import java.io.*;
- public class HelloWorldTag extends SimpleTagSupport
- {
- //重写doTag方法,该方法在标签结束生成页面内容
- public void doTag()throws JspException,
- IOException
- {
- //获取页面输出流,并输出字符串
- getJspContext().getOut().write("Hello World "
- + new java.util.Date());
- }
- }
2.11.2建立TLD文件
TLD(Tag Library Definition),标签库定义。标签库定义文件的根元素是taglib,它可以包含多个tag子元素,每个tag子元素都定义一个标签。
例子:mytaglib.tld
- <?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>http://www.crazyit.org/mytaglib</uri>
- <!-- 定义第一个标签 -->
- <tag>
- <!-- 定义标签名 -->
- <name>helloWorld</name>
- <!-- 定义标签处理类 -->
- <tag-class>lee.HelloWorldTag</tag-class>
- <!-- 定义标签体为空 -->
- <body-content>empty</body-content>
- </tag>
- </taglib>
2、使用标签:在JSP页面中使用自定义标签。
taglib的语法格式如下:
<%@ taglib uri="tagliburi" prefix="tagPrefix"%>
其中uri属性指定标签库的URI,这个URI可以确定一个标签库。而prefix属性指定标签库前缀,即所有使用该前缀的标签将由此标签库处理。
使用标签的语法格式如下:
<tagPrefix:tagName tagAttribute="tagValue" ...>
<tagBody/>
</tagPrefix:tagName>
如果该标签没有标签体,则可以使用如下语法格式:
<tagPrefix:tagName tagAttribute="tagValue" .../>
例子:helloWorldTag.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>
- <!-- 使用标签 ,其中mytag是标签前缀,根据taglib的编译指令,
- mytag前缀将由http://www.crazyit.org/mytaglib的标签库处理 -->
- <mytag:helloWorld/><br/>
- </body>
- </html>
2.11.4 带属性的标签
例子:QueryTag.java
- package lee;
- import javax.servlet.jsp.tagext.*;
- import javax.servlet.jsp.*;
- import java.io.*;
- import java.sql.*;
- public class QueryTag extends SimpleTagSupport
- {
- //标签的属性
- private String driver;
- private String url;
- private String user;
- private String pass;
- private String sql;
- //driver属性的setter和getter方法
- public void setDriver(String driver)
- {
- this.driver = driver;
- }
- public String getDriver()
- {
- return this.driver;
- }
- //url属性的setter和getter方法
- public void setUrl(String url)
- {
- this.url = url;
- }
- public String getUrl()
- {
- return this.url;
- }
- //user属性的setter和getter方法
- public void setUser(String user)
- {
- this.user = user;
- }
- public String getUser()
- {
- return this.user;
- }
- //pass属性的setter和getter方法
- public void setPass(String pass)
- {
- this.pass = pass;
- }
- public String getPass()
- {
- return this.pass;
- }
- //sql属性的setter和getter方法
- public void setSql(String sql)
- {
- this.sql = sql;
- }
- public String getSql()
- {
- return this.sql;
- }
- //conn属性的setter和getter方法
- public void setConn(Connection conn)
- {
- this.conn = conn;
- }
- public Connection getConn()
- {
- return this.conn;
- }
- //stmt属性的setter和getter方法
- public void setStmt(Statement stmt)
- {
- this.stmt = stmt;
- }
- public Statement getStmt()
- {
- return this.stmt;
- }
- //rs属性的setter和getter方法
- public void setRs(ResultSet rs)
- {
- this.rs = rs;
- }
- public ResultSet getRs()
- {
- return this.rs;
- }
- //rsmd属性的setter和getter方法
- public void setRsmd(ResultSetMetaData rsmd)
- {
- this.rsmd = rsmd;
- }
- public ResultSetMetaData getRsmd()
- {
- return this.rsmd;
- }
- //执行数据库访问的对象
- 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();
- }
- }
- }
- }
1、name:设置属性名,子元素的值是字符串内容
2、required:设置该属性是否为必须属性
3、fragment: 设置该属性是否支持JSP脚本、表达式等动态内容
- <!-- 定义第二个标签 -->
- <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>
- <%@ 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>
- <!-- 使用标签 ,其中mytag是标签前缀,根据taglib的编译指令,
- mytag前缀将由http://www.crazyit.org/mytaglib的标签库处理 -->
- <mytag:query
- driver="com.mysql.jdbc.Driver"
- url="jdbc:mysql://localhost:3306/javaee"
- user="root"
- pass="32147"
- sql="select * from news_inf"/><br/>
- </body>
- </html>
2.11.5 带标签体的标签
带标签体的标签,可以在标签内嵌入其他内容(包括静态的HTML内容和动态的JSP内容),通常用于完成一些逻辑运算,例如判断和循环等。
迭代器标签例子:IteratorTag.java
- package lee;
- import javax.servlet.jsp.tagext.*;
- import javax.servlet.jsp.*;
- import java.io.*;
- import java.sql.*;
- 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);
- }
- }
- }
因为该标签的标签体不为空,配置该标签时指定body-content为scripless
- <!-- 定义第三个标签 -->
- <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>
- <%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
- <%@ page import="java.util.*"%>
- <!-- 导入标签库,指定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>
- <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>
2.11.6以页面片段作为属性的标签
*标签处理类中定义类型为JspFragment的属性,该属性代表了“页面片段”;
*使用标签库时,通过<jsp:attribute.../>动作指令为标签的属性指定值。
例子:FragmentTag.java
- package lee;
- import javax.servlet.jsp.tagext.*;
- import javax.servlet.jsp.*;
- import java.io.*;
- 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");
- }
- }
- <tag>
- <!-- 定义标签名 -->
- <name>fragment</name>
- <!-- 定义标签处理类 -->
- <tag-class>lee.FragmentTag</tag-class>
- <!-- 指定该标签不支持标签体 -->
- <body-content>empty</body-content>
- <!-- 定义标签属性:fragment -->
- <attribute>
- <name>fragment</name>
- <required>true</required>
- <fragment>true</fragment>
- </attribute>
- </tag>
由于该标签需要一个fragment 属性,该属性的类型为JSPFragment,因此使用该标签时需要使用<jsp:attribute.../>动作指令来设置属性值。
- <%@ 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>
- <mytag:fragment>
- <!-- 使用jsp:attribute标签传入fragment参数 -->
- <jsp:attribute name="fragment">
- <!-- 下面是动态的JSP页面片段 -->
- <mytag:helloWorld/>
- </jsp:attribute>
- </mytag:fragment>
- <br/>
- <mytag:fragment>
- <jsp:attribute name="fragment">
- <!-- 下面是动态的JSP页面片段 -->
- ${pageContext.request.remoteAddr}
- </jsp:attribute>
- </mytag:fragment>
- </html>
2.11.7 动态属性的标签
我们需要传入自定义标签的属性个数是不确定的,属性名也不确定,这就需要借助于动态属性的标签了。
动态属性标签额外要求:
*标签处理类还需要实现DynamicAttributes接口。
*配置标签时通过<dynamic-attributes.../>子元素指定该标签支持动态属性。
例子:DynamicAttributesTag.java
- package lee;
- import javax.servlet.jsp.tagext.*;
- import javax.servlet.jsp.*;
- import java.io.*;
- import java.util.*;
- 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 );
- }
- }
配置标签:
- <!-- 定义接受动态属性的标签 -->
- <tag>
- <name>dynaAttr</name>
- <tag-class>lee.DynaAttributesTag</tag-class>
- <body-content>empty</body-content>
- <!-- 指定支持动态属性 -->
- <dynamic-attributes>true</dynamic-attributes>
- </tag>
- <%@ 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>