在本章中,我们将讨论JSP中的自定义标签。自定义标签是用户定义的JSP语言元素。当包含自定义标签的JSP页面被转换成一个servlet时,标签被转换为一个名为标签处理程序的对象的操作。 然后,Web容器在执行JSP页面的servlet时调用这些操作。
JSP标签扩展允许创建可以直接插入JSP的新标签。JSP 2.0规范引入了用于编写这些自定义标签的简单标签处理程序。
要编写自定义标签,可以简单地扩展SimpleTagSupport
类并覆盖doTag()
方法,可以在这个方法中放置代码来为标签生成内容。
为了更好的演示如何使用JSP中的自定义标签,打开Eclipse创建一个动态Web项目:CustomTags,其项目结构如下所示 -
假设要定义一个名为<ex:Hello>
的自定义标签,并且希望以下列方式来使用它:
<ex:Hello />
要创建自定义JSP标记,必须首先创建一个充当标记处理程序的Java
类。在这个示例中创建一个HelloTag
类,如下所示:
文件:HelloTag.java
package com.zyiz; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import java.io.*; public class HelloTag extends SimpleTagSupport { public void doTag() throws JspException, IOException { JspWriter out = getJspContext().getOut(); out.println("您好,这是一个自定义标签内容!"); } }
上述代码只是简单的编码,其中doTag()
方法使用getJspContext()
方法获取当前的JspContext
对象,并使用它发送“Hello Custom Tag!”
到当前的JspWriter
对象
最后,创建以下标签库文件:
<taglib> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>Custom TLD</short-name> <tag> <name>Hello</name> <tag-class>com.zyiz.HelloTag</tag-class> <body-content>empty</body-content> </tag> </taglib>
在JSP程序中使用上面定义的自定义标签Hello
,如下所示:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!-- 需要指示定义的声明文件 --> <%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%> <!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>自定义标签示例</title> </head> <body> <div style="margin: auto; width: 80%"> <b>以下是自定义标签输出的内容:</b><hr/> <ex:Hello/> </div> </body> </html>
调用上述JSP,这应该产生以下结果 -
可以在标签正文中添加一条消息,如标准标签所示。 考虑想定义一个名为<ex:Hello>
的自定义标签,并且使用下面的方式来使用它 -
<ex:Hello> This is message body </ex:Hello>
在上述标签代码中进行以下更改来处理标签的正文 -
package com.zyiz; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import java.io.*; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import java.io.*; public class HelloTag extends SimpleTagSupport { StringWriter sw = new StringWriter(); public void doTag() throws JspException, IOException { getJspBody().invoke(sw); getJspContext().getOut().println(sw.toString()); } }
这里,由调用产生的输出首先捕获到一个StringWriter
中,然后再写入与该标签关联的JspWriter
。需要更改TLD文件,如下所示:
文件:custom.tld
<taglib> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>Example TLD with Body</short-name> <tag> <name>Hello</name> <tag-class>com.zyiz.HelloTag</tag-class> <body-content>scriptless</body-content> </tag> </taglib>
现在在正文中调用上面的标签,如下所示:
文件:index2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!-- 需要指示定义的声明文件 --> <%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%> <!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>自定义标签示例</title> </head> <body> <div style="margin: auto; width: 80%"> <b>以下是自定义标签输出的内容:</b> <hr /> <ex:Hello> 这是标签体的内容 </ex:Hello> </div> </body> </html>
执行上面示例代码,将得到以下结果 -
也可以使用各种属性以及自定义标签。要接受属性值,自定义标签类需要实现setter
方法,与JavaBean setter
方法相同,如下所示:
文件:CTagAttr.java
package com.zyiz; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import java.io.*; public class CTagAttr extends SimpleTagSupport { private String message; public void setMessage(String msg) { this.message = msg; } StringWriter sw = new StringWriter(); public void doTag() throws JspException, IOException { if (message != null) { /* Use message from attribute */ JspWriter out = getJspContext().getOut(); out.println( message ); } else { /* use message from the body */ getJspBody().invoke(sw); getJspContext().getOut().println(sw.toString()); } } }
属性的名称是message
,所以setter
方法是setMessage()
。现在使用<attribute>
元素在TLD文件中添加此属性,如下所示:
<taglib> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>Example TLD with Body</short-name> <tag> <name>Hello</name> <tag-class>com.zyiz.CTagAttr</tag-class> <body-content>scriptless</body-content> <attribute> <name>message</name> </attribute> </tag> </taglib>
在JSP中使用HelloTag的message
属性如下 -
文件:ctagattr.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!-- 需要指示定义的声明文件 --> <%@ taglib prefix="ex" uri="WEB-INF/ctagattr.tld"%> <!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>自定义标签属性示例</title> </head> <body> <div style="margin: auto; width: 80%"> <b>以下是自定义标签输出的内容:</b><hr/> <ex:Hello message = "This is custom tag attribute" /> </div> </body> </html>
这将产生以下结果 -
下面是包括的属性及说明 -
编号 | 属性 | 描述 |
---|---|---|
1 | name |
name 元素定义属性的名称。每个属性名称对于特定标签必须是唯一的。 |
2 | required |
此规范如果此属性是必需的或是可选的。则可设置为:false 。 |
3 | rtexprvalue |
声明tag 属性的运行时表达式值是否有效 |
4 | type |
定义此属性的Java类类型。 默认情况下,它被假定为String 类型 |
5 | description |
可以提供信息描述。 |
6 | fragment |
声明此属性值是否应被视为JspFragment。 |
以下是指定属性相关属性的示例 -
..... <attribute> <name>attribute_name</name> <required>false</required> <type>java.util.Date</type> <fragment>false</fragment> </attribute> .....
如果使用两个属性,则可以按如下所示修改TLD:
..... <attribute> <name>attribute_name1</name> <required>false</required> <type>java.util.Boolean</type> <fragment>false</fragment> </attribute> <attribute> <name>attribute_name2</name> <required>true</required> <type>java.util.Date</type> </attribute> .....
在上面几个示例中,我们已经演示了如何创建一个自定义标签,打印给定标签名称和特定属性内容。这里将进一步演示如何在自定义标签中读取数据库表中的数据记录。假设要使用自定义标签来显示最新入职的3
名员工,参考以下实现步骤。
创建数据库和表 -
DROP TABLE IF EXISTS `employees`; CREATE TABLE `employees` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL DEFAULT '', `age` int(3) unsigned NOT NULL DEFAULT '0', `education` varchar(32) DEFAULT '' COMMENT '学历', `address` varchar(254) DEFAULT NULL, `salary` float(8,2) unsigned DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=16 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of employees -- ---------------------------- INSERT INTO `employees` VALUES ('1', '李家诚', '23', '其它', '海口市人民大道1800号', '8900.00'); INSERT INTO `employees` VALUES ('2', '张辉', '28', '本科', '广州天河区珠村市场', '19999.99'); INSERT INTO `employees` VALUES ('3', '林贤弟', '29', '博士', '广州白云区龙塘村120号', '18990.99'); INSERT INTO `employees` VALUES ('4', '王小简', '23', '本科', '海口人民大道1688号', '899.98'); INSERT INTO `employees` VALUES ('5', '蔡世杰', '27', '专科', '上海市宝山区联杨路2211弄26号', '15800.00');
创建一个Java类文件:Employee.java
package com.zyiz; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; import java.sql.*; public class EmployeeTag extends TagSupport { private String number; public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public int doStartTag() throws JspException { JspWriter out = pageContext.getOut(); try { Class.forName("com.mysql.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mysql://localhost/testdb?useSSL=false&characterEncoding=utf8", "root", "123456"); PreparedStatement ps = con.prepareStatement("SELECT name,education,age FROM `employees` ORDER BY id DESC limit "+this.number); //ps.setInt(1, Integer.parseInt(this.number)); System.out.println("number => "+this.number); ResultSet rs = ps.executeQuery(); if (rs != null) { // column name out.write("<table border='1'>"); out.write("<tr>"); out.write("<th>姓名</th><th>学历</th><th>年龄</th>"); out.write("</tr>"); // column value while (rs.next()) { out.write("<tr>"); out.write("<td>" + rs.getString("name") + "</td><td>" + rs.getString("education") + "</td><td>" + rs.getString("age") + "</td>"); out.write("</tr>"); } out.write("</table>"); } con.close(); } catch (Exception e) { System.out.println(e); } return SKIP_BODY; } }
文件:empl.tld
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.2</tlib-version> <jsp-version>2.0</jsp-version> <short-name>c</short-name> <uri>zyiz</uri> <tag> <name>NewEmpl</name> <tag-class>com.zyiz.EmployeeTag</tag-class> <attribute> <name>number</name> <required>true</required> </attribute> </tag> </taglib>
文件:new_empl.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="ex" uri="WEB-INF/empl.tld"%> <!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>自定义标签+数据库</title> </head> <body> <center> 最新加入的3位员工: <hr /> <ex:NewEmpl number="3"/> </center> </body> </html>
在编写完成上面示例代码后,运行这个JSP文件,应该会看到以下结果 -