JSP自定義標籤
在本章中,我們將討論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.yiibai;
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
對象
最後,創建以下標籤庫文件: {webapps}/WEB-INF/custom.tld , 內容如下 -
<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.yiibai.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.yiibai;
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.yiibai.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.yiibai;
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.yiibai.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>
.....
JSP自定義標籤屬性操作數據庫示例
在上面幾個示例中,我們已經演示瞭如何創建一個自定義標籤,打印給定標籤名稱和特定屬性內容。這裏將進一步演示如何在自定義標籤中讀取數據庫表中的數據記錄。假設要使用自定義標籤來顯示最新入職的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.yiibai;
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>yiibai</uri>
<tag>
<name>NewEmpl</name>
<tag-class>com.yiibai.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文件,應該會看到以下結果 -