2.8.4 带属性的标签
前面的简单标签既没有属性,也没有标签体用法、功能都比较简单。实际上还有如下两种常用的标签。
正如前面介绍的,带属性标签必须为每个属性提供对应的settr
和gettr
方法。带属性标签的配置方法与简单标签也略有差别,下面介绍一个带属性标签的示例:
QueryTag.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
| 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;
public void setDriver(String driver) { this.driver = driver; }
public String getDriver() { return this.driver; }
public void setUrl(String url) { this.url = url; }
public String getUrl() { return this.url; }
public void setUser(String user) { this.user = user; }
public String getUser() { return this.user; }
public void setPass(String pass) { this.pass = pass; }
public String getPass() { return this.pass; }
public void setSql(String sql) { this.sql = sql; }
public String getSql() { return this.sql; }
private Connection conn = null; private Statement stmt = null; private ResultSet rs = null; private ResultSetMetaData rsmd = null; public void setConn(Connection conn) { this.conn = conn; }
public Connection getConn() { return this.conn; }
public void setStmt(Statement stmt) { this.stmt = stmt; }
public Statement getStmt() { return this.stmt; }
public void setRs(ResultSet rs) { this.rs = rs; }
public ResultSet getRs() { return this.rs; }
public void setRsmd(ResultSetMetaData rsmd) { this.rsmd = rsmd; }
public ResultSetMetaData getRsmd() { return this.rsmd; }
public void doTag() throws JspException, IOException { try { Class.forName(driver); conn = DriverManager.getConnection(url, user, pass); 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(); } } } }
|
上面这个标签稍微复杂一点,它包含了5个属性,如程序中粗体字代码所示(为标签处理类定义成员变量即可代表标签的属性),程序需要为这5个属性提供setter
和getter
方法。
该标签输出的内容依然由doTag()
方法决定,该方法会根据SQL
语句查询数据库,并将查询结果显示在当前页面中。
对于有属性的标签,需要为tag
元素增加attribute
子元素,每个attribute
子元素定义一个标签属性。attribute
子元素通常还需要指定如下几个子元素:
name
:设置属性名,子元素的值是字符串内容
required
:设置该属性是否为必需属性,该子元素的值是true
或false
fragment
:设置该属性是否支持JSP
脚本、表达式等动态内容,子元素的值是true
或false
为了配置上面的QueryTag
标签,需要在mytaglib.TLD
文件中增加如下配置片段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <tag> <name>query</name> <tag-class>lee.QueryTag</tag-class> <body-content>empty</body-content>
<attribute> <name>driver</name> <required>true</required> <fragment>true</fragment> </attribute> <attribute> <name>url</name> <required>true</required> <fragment>true</fragment> </attribute> <attribute> <name>user</name> <required>true</required> <fragment>true</fragment> </attribute> <attribute> <name>pass</name> <required>true</required> <fragment>true</fragment> </attribute> <attribute> <name>sql</name> <required>true</required> <fragment>true</fragment> </attribute> </tag>
|
上面代码分别为该标签配置了driver
、url
、user
、pass
和sql
五个属性,并指定这5个属性都是必需属性,而且属性值支持动态内容.
配置完毕后,就可在页面中使用标签了,先导入标签库,然后使用标签。使用标签的JSP
页面片段如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %> <!-- 导入标签库,指定mytag前缀的标签, 由http: <%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%> <!DOCTYPE html> <html> <head> <title>自定义标签示范</title> </head> <body bgcolor="#ffffc0"> <h2>下面显示的是查询标签的结果</h2> <!-- 使用标签 ,其中mytag是标签前缀,根据taglib的编译指令, mytag前缀将由http: <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.35所示。
在JSP
页面中只需要使用简单的标签,即可完成“复杂”的功能:执行数据库查询,并将查询结果在页面上以表格形式显示。这也正是自定义标签库的目的以简单的标签,隐藏复杂的逻辑。
当然,并不推荐在标签处理类中访问数据库,因为标签库是表现层组件,它不应该包含任何业务逻辑实现代码,更不应该执行数据库访问,它只应该负责显示逻辑。
第三方标签库
JSTL
是Sun
提供的一套标签库,这套标签库的功能非常强大。
- 另外,
DisplayTag
是Apache
组织下的一套开源标签库,主要用于生成页面并显示效果