橘子味的心
标题:JSP自定义标签

在本章中,我们将讨论JSP中的自定义标签。自定义标签是用户定义的JSP语言元素。当包含自定义标签的JSP页面被转换成一个servlet时,标签被转换为一个名为标签处理程序的对象的操作。 然后,Web容器在执行JSP页面的servlet时调用这些操作。

JSP标签扩展允许创建可以直接插入JSP的新标签。JSP 2.0规范引入了用于编写这些自定义标签的简单标签处理程序。

要编写自定义标签,可以简单地扩展SimpleTagSupport类并覆盖doTag()方法,可以在这个方法中放置代码来为标签生成内容。

创建标签示例

为了更好的演示如何使用JSP中的自定义标签,打开Eclipse创建一个动态Web项目:CustomTags,其项目结构如下所示 -

假设要定义一个名为<ex:Hello>的自定义标签,并且希望以下列方式来使用它:

  1. <ex:Hello />
  2. XML

要创建自定义JSP标记,必须首先创建一个充当标记处理程序的Java类。在这个示例中创建一个HelloTag类,如下所示:

文件:HelloTag.java

  1. package com.yiibai;
  2.  
  3. import javax.servlet.jsp.tagext.*;
  4. import javax.servlet.jsp.*;
  5. import java.io.*;
  6.  
  7. public class HelloTag extends SimpleTagSupport {
  8. public void doTag() throws JspException, IOException {
  9. JspWriter out = getJspContext().getOut();
  10. out.println("您好,这是一个自定义标签内容!");
  11. }
  12. }
  13. Java

上述代码只是简单的编码,其中doTag()方法使用getJspContext()方法获取当前的JspContext对象,并使用它发送“Hello Custom Tag!”到当前的JspWriter对象

最后,创建以下标签库文件:{webapps}/WEB-INF/custom.tld , 内容如下 -

  1. <taglib>
  2. <tlib-version>1.0</tlib-version>
  3. <jsp-version>2.0</jsp-version>
  4. <short-name>Custom TLD</short-name>
  5. <tag>
  6. <name>Hello</name>
  7. <tag-class>com.yiibai.HelloTag</tag-class>
  8. <body-content>empty</body-content>
  9. </tag>
  10. </taglib>
  11. XML

在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>的自定义标签,并且使用下面的方式来使用它 -

  1. <ex:Hello>
  2. This is message body
  3. </ex:Hello>
  4. XML

在上述标签代码中进行以下更改来处理标签的正文 -

  1. package com.yiibai;
  2.  
  3. import javax.servlet.jsp.tagext.*;
  4. import javax.servlet.jsp.*;
  5. import java.io.*;
  6.  
  7. import javax.servlet.jsp.tagext.*;
  8. import javax.servlet.jsp.*;
  9. import java.io.*;
  10.  
  11. public class HelloTag extends SimpleTagSupport {
  12. StringWriter sw = new StringWriter();
  13.  
  14. public void doTag()
  15.  
  16. throws JspException, IOException {
  17. getJspBody().invoke(sw);
  18. getJspContext().getOut().println(sw.toString());
  19. }
  20. }
  21. Java

这里,由调用产生的输出首先捕获到一个StringWriter中,然后再写入与该标签关联的JspWriter。需要更改TLD文件,如下所示:

文件:custom.tld

  1. <taglib>
  2. <tlib-version>1.0</tlib-version>
  3. <jsp-version>2.0</jsp-version>
  4. <short-name>Example TLD with Body</short-name>
  5.  
  6. <tag>
  7. <name>Hello</name>
  8. <tag-class>com.yiibai.HelloTag</tag-class>
  9. <body-content>scriptless</body-content>
  10. </tag>
  11. </taglib>
  12. XML

现在在正文中调用上面的标签,如下所示:

文件:index2.jsp

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!-- 需要指示定义的声明文件 -->
  4. <%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%>
  5. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  6. <html>
  7. <head>
  8. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  9. <title>自定义标签示例</title>
  10. </head>
  11. <body>
  12. <div style="margin: auto; width: 80%">
  13. <b>以下是自定义标签输出的内容:</b>
  14. <hr />
  15. <ex:Hello>
  16. 这是标签体的内容
  17. </ex:Hello>
  18. </div>
  19.  
  20. </body>
  21. </html>
  22. HTML

执行上面示例代码,将得到以下结果 -

自定义标签属性

也可以使用各种属性以及自定义标签。要接受属性值,自定义标签类需要实现setter方法,与JavaBean setter方法相同,如下所示:

文件:CTagAttr.java

  1. package com.yiibai;
  2.  
  3.  
  4. import javax.servlet.jsp.tagext.*;
  5. import javax.servlet.jsp.*;
  6. import java.io.*;
  7.  
  8. public class CTagAttr extends SimpleTagSupport {
  9. private String message;
  10.  
  11. public void setMessage(String msg) {
  12. this.message = msg;
  13. }
  14. StringWriter sw = new StringWriter();
  15. public void doTag()
  16.  
  17. throws JspException, IOException {
  18. if (message != null) {
  19. /* Use message from attribute */
  20. JspWriter out = getJspContext().getOut();
  21. out.println( message );
  22. } else {
  23. /* use message from the body */
  24. getJspBody().invoke(sw);
  25. getJspContext().getOut().println(sw.toString());
  26. }
  27. }
  28. }
  29. Java

属性的名称是message,所以setter方法是setMessage()。现在使用<attribute>元素在TLD文件中添加此属性,如下所示:

  1. <taglib>
  2. <tlib-version>1.0</tlib-version>
  3. <jsp-version>2.0</jsp-version>
  4. <short-name>Example TLD with Body</short-name>
  5.  
  6. <tag>
  7. <name>Hello</name>
  8. <tag-class>com.yiibai.CTagAttr</tag-class>
  9. <body-content>scriptless</body-content>
  10.  
  11. <attribute>
  12. <name>message</name>
  13. </attribute>
  14.  
  15. </tag>
  16. </taglib>
  17. XML

在JSP中使用HelloTag的message属性如下 -

文件:ctagattr.jsp

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!-- 需要指示定义的声明文件 -->
  4. <%@ taglib prefix="ex" uri="WEB-INF/ctagattr.tld"%>
  5. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  6. <html>
  7. <head>
  8. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  9. <title>自定义标签属性示例</title>
  10. </head>
  11. <body>
  12. <div style="margin: auto; width: 80%">
  13. <b>以下是自定义标签输出的内容:</b><hr/>
  14. <ex:Hello message = "This is custom tag attribute" />
  15. </div>
  16.  
  17. </body>
  18. </html>
  19. HTML

这将产生以下结果 -

下面是包括的属性及说明 -

编号 属性 描述
1 name name元素定义属性的名称。每个属性名称对于特定标签必须是唯一的。
2 required 此规范如果此属性是必需的或是可选的。则可设置为:false
3 rtexprvalue 声明tag属性的运行时表达式值是否有效
4 type 定义此属性的Java类类型。 默认情况下,它被假定为String类型
5 description 可以提供信息描述。
6 fragment 声明此属性值是否应被视为JspFragment。

以下是指定属性相关属性的示例 -

  1. .....
  2. <attribute>
  3. <name>attribute_name</name>
  4. <required>false</required>
  5. <type>java.util.Date</type>
  6. <fragment>false</fragment>
  7. </attribute>
  8. .....
  9. XML

如果使用两个属性,则可以按如下所示修改TLD:

  1. .....
  2. <attribute>
  3. <name>attribute_name1</name>
  4. <required>false</required>
  5. <type>java.util.Boolean</type>
  6. <fragment>false</fragment>
  7. </attribute>
  8.  
  9. <attribute>
  10. <name>attribute_name2</name>
  11. <required>true</required>
  12. <type>java.util.Date</type>
  13. </attribute>
  14. .....
  15. XML

JSP自定义标签属性操作数据库示例

在上面几个示例中,我们已经演示了如何创建一个自定义标签,打印给定标签名称和特定属性内容。这里将进一步演示如何在自定义标签中读取数据库表中的数据记录。假设要使用自定义标签来显示最新入职的3名员工,参考以下实现步骤。

创建数据库和表 -

  1. DROP TABLE IF EXISTS `employees`;
  2. CREATE TABLE `employees` (
  3. `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  4. `name` varchar(64) NOT NULL DEFAULT '',
  5. `age` int(3) unsigned NOT NULL DEFAULT '0',
  6. `education` varchar(32) DEFAULT '' COMMENT '学历',
  7. `address` varchar(254) DEFAULT NULL,
  8. `salary` float(8,2) unsigned DEFAULT NULL,
  9. PRIMARY KEY (`id`)
  10. ) ENGINE=MyISAM AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
  11.  
  12. -- ----------------------------
  13. -- Records of employees
  14. -- ----------------------------
  15. INSERT INTO `employees` VALUES ('1', '李家诚', '23', '其它', '海口市人民大道1800号', '8900.00');
  16. INSERT INTO `employees` VALUES ('2', '张辉', '28', '本科', '广州天河区珠村市场', '19999.99');
  17. INSERT INTO `employees` VALUES ('3', '林贤弟', '29', '博士', '广州白云区龙塘村120号', '18990.99');
  18. INSERT INTO `employees` VALUES ('4', '王小简', '23', '本科', '海口人民大道1688号', '899.98');
  19. INSERT INTO `employees` VALUES ('5', '蔡世杰', '27', '专科', '上海市宝山区联杨路2211弄26号', '15800.00');
  20. SQL

创建一个Java类文件:Employee.java

  1. package com.yiibai;
  2.  
  3. import javax.servlet.jsp.JspException;
  4. import javax.servlet.jsp.JspWriter;
  5. import javax.servlet.jsp.tagext.TagSupport;
  6. import java.sql.*;
  7.  
  8. public class EmployeeTag extends TagSupport {
  9. private String number;
  10.  
  11. public String getNumber() {
  12. return number;
  13. }
  14.  
  15. public void setNumber(String number) {
  16. this.number = number;
  17. }
  18.  
  19. public int doStartTag() throws JspException {
  20. JspWriter out = pageContext.getOut();
  21. try {
  22. Class.forName("com.mysql.jdbc.Driver");
  23. Connection con = DriverManager.getConnection("jdbc:mysql://localhost/testdb?useSSL=false&characterEncoding=utf8", "root", "123456");
  24. PreparedStatement ps = con.prepareStatement("SELECT name,education,age FROM `employees` ORDER BY id DESC limit "+this.number);
  25. //ps.setInt(1, Integer.parseInt(this.number));
  26. System.out.println("number => "+this.number);
  27. ResultSet rs = ps.executeQuery();
  28. if (rs != null) {
  29. // column name
  30. out.write("<table border='1'>");
  31. out.write("<tr>");
  32. out.write("<th>姓名</th><th>学历</th><th>年龄</th>");
  33. out.write("</tr>");
  34. // column value
  35.  
  36. while (rs.next()) {
  37. out.write("<tr>");
  38. out.write("<td>" + rs.getString("name") + "</td><td>" + rs.getString("education") + "</td><td>" + rs.getString("age") + "</td>");
  39. out.write("</tr>");
  40. }
  41. out.write("</table>");
  42. }
  43. con.close();
  44. } catch (Exception e) {
  45. System.out.println(e);
  46. }
  47. return SKIP_BODY;
  48. }
  49. }
  50. Java

文件:empl.tld

  1. <?xml version="1.0" encoding="ISO-8859-1" ?>
  2. <!DOCTYPE taglib
  3. PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
  4. "http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd">
  5.  
  6. <taglib>
  7.  
  8. <tlib-version>1.2</tlib-version>
  9. <jsp-version>2.0</jsp-version>
  10. <short-name>c</short-name>
  11. <uri>yiibai</uri>
  12.  
  13. <tag>
  14. <name>NewEmpl</name>
  15. <tag-class>com.yiibai.EmployeeTag</tag-class>
  16. <attribute>
  17. <name>number</name>
  18. <required>true</required>
  19. </attribute>
  20. </tag>
  21. </taglib>
  22. XML

文件:new_empl.jsp

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <%@ taglib prefix="ex" uri="WEB-INF/empl.tld"%>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  8. <title>自定义标签+数据库</title>
  9. </head>
  10. <body>
  11. <center>
  12. 最新加入的3位员工:
  13. <hr />
  14. <ex:NewEmpl number="3"/>
  15. </center>
  16. </body>
  17. </html>
  18. HTML

在编写完成上面示例代码后,运行这个JSP文件,应该会看到以下结果 -