Jsp2的自定义标签
Jsp2 开发标签库的几个步骤:
- 开发自定义标签处理类。
- 建立一个*.tld文件,每个tld文件对应一个标签库,每个标签库可对应多个标签。
- 在jsp文件中使用自定义标签
空标签
开发自定义标签类
- 自定义标签类应该继承一个父类javax.servlet.jsp.tagext.SimpleTagSupport;
- 如果标签类包含属性,每个属性都有对应的getter 和settter方法;
- 重写doTag()方法,这个方法负责生成页面内容
建立一个简单的自定义标签,在页面上输出HelloWorld
1 package com.dev.sen; 2 3 import java.io.IOException; 4 5 import javax.servlet.jsp.JspException; 6 import javax.servlet.jsp.tagext.SimpleTagSupport; 7 /** 8 * 自定义标签在页面上输出hello World 9 * @author WangSen 10 * @date 2014-6-28 11 * @time 下午7:22:36 12 */ 13 public class HelloWorldTag extends SimpleTagSupport { 14 /** 15 * 重写doTag方法,该方法在标签结束生成页面内容 16 */ 17 @Override 18 public void doTag() throws JspException, IOException { 19 getJspContext().getOut().write("Hello World !"); 20 } 21 22 }
建立TlD文件
TLD是Tag Library Definition,标签库的定义文件的根元素是taglib,它可以包含多个tag子元素,每个tag子元素定义一个标签 ,部署标签库文件,只需要将tld文件存放在WEB-INF/路径,或者WEB-INF的任意子路径下。
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" 4 version="2.0"> 5 <description>my customTag</description> 6 <tlib-version>1.0</tlib-version> 7 <short-name>mytag</short-name> 8 <!-- 标签库的URL --> 9 <uri>http://www.dev.com/taglib</uri> 10 <tag> 11 <description>Outputs Hello, World</description> 12 <!-- 标签名 --> 13 <name>helloWorld</name> 14 <!-- 标签处理类 --> 15 <tag-class>com.dev.sen.HelloWorldTag</tag-class> 16 <!-- 定义标签体为空 --> 17 <body-content>empty</body-content> 18 </tag> 19 </taglib>
元素说明:
使用标签库
在jsp页面中确定指定的标签需要两点,
- 标签库的URI:确定使用那个标签库。
- 标签名:确定使用那个标签。
使用标签库的步骤
- 导入标签库:使用taglib编译指令导入标签库,就是将标签库和指定前缀关联起来。
- 使用标签:在jsp页面中使用自定义标签。
带属性的标签
开发自定义标签类
1 package com.dev.sen; 2 3 import java.io.IOException; 4 import java.sql.Connection; 5 import java.sql.DriverManager; 6 import java.sql.ResultSet; 7 import java.sql.ResultSetMetaData; 8 import java.sql.SQLException; 9 import java.sql.Statement; 10 11 import javax.servlet.jsp.JspException; 12 import javax.servlet.jsp.JspWriter; 13 import javax.servlet.jsp.tagext.SimpleTagSupport; 14 15 /** 16 * 根据sql语句查询数据库 17 * 18 * @author WangSen 19 * @date 2014-6-28 20 * @time 下午8:50:19 21 */ 22 public class QueryTag extends SimpleTagSupport { 23 private String driver; 24 private String url; 25 private String user; 26 private String password; 27 private String sql; 28 29 public String getDriver() { 30 return driver; 31 } 32 33 public void setDriver(String driver) { 34 this.driver = driver; 35 } 36 37 public String getUrl() { 38 return url; 39 } 40 41 public void setUrl(String url) { 42 this.url = url; 43 } 44 45 public String getUser() { 46 return user; 47 } 48 49 public void setUser(String user) { 50 this.user = user; 51 } 52 53 public String getPassword() { 54 return password; 55 } 56 57 public void setPassword(String password) { 58 this.password = password; 59 } 60 61 public String getSql() { 62 return sql; 63 } 64 65 public void setSql(String sql) { 66 this.sql = sql; 67 } 68 /** 69 * 执行sql查询并输出结果 70 */ 71 @Override 72 public void doTag() throws JspException, IOException { 73 Connection conn = null; 74 Statement st = null; 75 ResultSet rs = null; 76 ResultSetMetaData rsmd = null; 77 try { 78 Class.forName(driver);//注册驱动 79 conn = DriverManager.getConnection(url,user,password);//获取连接 80 st = conn.createStatement();//创建Statement 81 rs = st.executeQuery(sql); //执行查询 82 rsmd = rs.getMetaData(); 83 //获取列数目 84 int columnConout = rsmd.getColumnCount(); 85 //获取页面输出流 86 JspWriter out = getJspContext().getOut(); 87 //在页面输出表格 88 out.write("<table border='1' bgcolor='#9999cc' width='400'>"); 89 while (rs.next()) { 90 out.write("<tr>"); 91 //逐列遍历查询到的数据 92 for (int i = 0; i < columnConout; i++) { 93 out.write("<td>"); 94 out.write(rs.getString(i+1)); 95 out.write("</td>"); 96 } 97 out.write("</tr>"); 98 } 99 out.write("</table>"); 100 } catch (ClassNotFoundException e) { 101 e.printStackTrace(); 102 throw new JspException("自定义标签错误", e); 103 } catch (SQLException e) { 104 e.printStackTrace(); 105 throw new JspException("自定义标签错误", e); 106 }finally{ 107 try { 108 //关闭结果集 109 if(rs!=null&&!rs.isClosed()){ 110 rs.close(); 111 } 112 if(st!=null&&!st.isClosed()){ 113 st.close(); 114 } 115 if(conn!=null&&!conn.isClosed()){ 116 conn.close(); 117 } 118 } catch (SQLException e) { 119 e.printStackTrace(); 120 } 121 } 122 123 } 124 }
在tld文件中配置标签
在上文中的tld文件中增加一个tag标签,内容如下
1 <!-- 定义带属性的标签 --> 2 <tag> 3 <description>根据sql语句查询数据库</description> 4 <name>query</name> 5 <tag-class>com.dev.sen.QueryTag</tag-class> 6 <body-content>empty</body-content> 7 <!-- 配置标签属性 --> 8 <attribute> 9 <description>driverName</description> 10 <name>driver</name> 11 <required>true</required> 12 <fragment>true</fragment> 13 </attribute> 14 <attribute> 15 <description>url</description> 16 <name>url</name> 17 <required>true</required> 18 <fragment>true</fragment> 19 </attribute> 20 <attribute> 21 <description>user</description> 22 <name>user</name> 23 <required>true</required> 24 <fragment>true</fragment> 25 </attribute> 26 <attribute> 27 <description>password</description> 28 <name>password</name> 29 <required>true</required> 30 <fragment>true</fragment> 31 </attribute> 32 <attribute> 33 <description>querysql</description> 34 <name>sql</name> 35 <required>true</required> 36 <fragment>true</fragment> 37 </attribute> 38 </tag>
使用标签
带标签体的标签
开发自定义标签类
1 package com.dev.sen; 2 3 import java.io.IOException; 4 import java.util.Collection; 5 6 import javax.servlet.jsp.JspException; 7 import javax.servlet.jsp.tagext.SimpleTagSupport; 8 9 /** 10 * 迭代输出集合元素 11 * 12 * @author WangSen 13 * @date 2014-6-28 14 * @time 下午9:28:51 15 */ 16 public class IteratorTag extends SimpleTagSupport { 17 private String collection; 18 private String item; 19 20 public String getCollection() { 21 return collection; 22 } 23 24 public void setCollection(String collection) { 25 this.collection = collection; 26 } 27 28 public String getItem() { 29 return item; 30 } 31 32 public void setItem(String item) { 33 this.item = item; 34 } 35 36 @SuppressWarnings("rawtypes") 37 @Override 38 public void doTag() throws JspException, IOException { 39 // 从page scope 中获取属性名为collection的集合 40 Collection itemList = (Collection) getJspContext().getAttribute( 41 collection); 42 // 遍历集合 43 for (Object s : itemList) { 44 //将集合元素设置到page scope中 45 getJspContext().setAttribute(item, s); 46 /* 输出标签体 47 *getJspBody()方法返回标签所包含的标签体:JspFragment对象 48 *执行该对象的invoke()方法,即可输出标签体的内容 49 */ 50 getJspBody().invoke(null); 51 } 52 } 53 54 }
getJspBody()方法返回标签所包含的标签体:JspFragment对象,执行该对象的invoke()方法,即可输出标签体的内容
在tld文件中配置标签
在上文中的tld文件中增加一个tag标签,内容如下
1 <tag> 2 <description>Iterator Tag</description> 3 <name>iterator</name> 4 <tag-class>com.dev.sen.IteratorTag</tag-class> 5 <body-content>scriptless</body-content> 6 <attribute> 7 <description>collection name </description> 8 <name>collection</name> 9 <required>true</required> 10 <fragment>true</fragment> 11 </attribute> 12 <attribute> 13 <description>item</description> 14 <name>item</name> 15 <required>true</required> 16 <fragment>true</fragment> 17 </attribute> 18 </tag>
使用标签
以页面片段作为属性的标签
以页面片段作为属性的标签与普通标签区别并不大,只有两个简单的改变
- 标签处理类中定义类型为JspFragment的属性,该属性代表”页面片段”
- 使用标签库时使用<jsp:attribute…>动作指令为标签库属性指定值。
开发自定义标签类
1 package com.dev.sen; 2 3 import java.io.IOException; 4 5 import javax.servlet.jsp.JspException; 6 import javax.servlet.jsp.JspWriter; 7 import javax.servlet.jsp.tagext.JspFragment; 8 import javax.servlet.jsp.tagext.SimpleTagSupport; 9 10 /** 11 * 以页面片段做为属性的标签 12 * 13 * @author WangSen 14 * @date 2014-6-28 15 * @time 下午10:56:40 16 */ 17 public class FragmentTag extends SimpleTagSupport { 18 private JspFragment fragment; 19 20 public JspFragment getFragment() { 21 return fragment; 22 } 23 24 public void setFragment(JspFragment fragment) { 25 this.fragment = fragment; 26 } 27 28 @Override 29 public void doTag() throws JspException, IOException { 30 JspWriter out = getJspContext().getOut(); 31 out.println("<div style='padding:10px;border:1px solid black'>"); 32 out.println("<h3>下面是动态传入的jsp片段</h3>"); 33 //调用 输出页面片段 34 fragment.invoke(null); 35 out.println("</div>"); 36 } 37 38 }
在tld文件中配置标签
在上文中的tld文件中增加一个tag标签,内容如下
1 <!-- 以页面片段作为属性的标签 --> 2 <tag> 3 <name>fragment</name> 4 <tag-class>com.dev.sen.FragmentTag</tag-class> 5 <!-- 指定该标签不支持标签体 --> 6 <body-content>empty</body-content> 7 <attribute> 8 <name>fragment</name> 9 <required>true</required> 10 <fragment>true</fragment> 11 </attribute> 12 </tag>
使用标签
动态属性的标签
开发自定义标签类
动态属性标签比普通标签多如下两个额外要求
- 处理类还需要实现DynamicAttributes接口
- 配置标签时通过<dynamic-attributes../>子元素指定该标签支持动态属性
1 package com.dev.sen; 2 3 import java.io.IOException; 4 import java.util.ArrayList; 5 6 import javax.servlet.jsp.JspException; 7 import javax.servlet.jsp.JspWriter; 8 import javax.servlet.jsp.tagext.DynamicAttributes; 9 import javax.servlet.jsp.tagext.SimpleTagSupport; 10 /** 11 * 动态属性标签 12 * @author WangSen 13 * @date 2014-6-28 14 * @time 下午11:33:33 15 */ 16 public class DynaAttributesTag extends SimpleTagSupport implements 17 DynamicAttributes { 18 // 保存属性名的集合 19 private ArrayList<String> keys = new ArrayList<String>(); 20 // 保存属性值的集合 21 private ArrayList<Object> values = new ArrayList<Object>(); 22 23 @Override 24 public void doTag() throws JspException, IOException { 25 super.doTag(); 26 JspWriter out = getJspContext().getOut(); 27 out.println("<ol>"); 28 for (int i = 0; i < keys.size(); i++) { 29 out.println("<li>"+keys.get(i)+"="+values.get(i)+"</li>"); 30 } 31 out.println("</ol>"); 32 } 33 34 @Override 35 public void setDynamicAttribute(String uri, String key, Object value) 36 throws JspException { 37 //添加属性名 38 keys.add(key); 39 //添加属性值 40 values.add(value); 41 } 42 }
在tld文件中配置标签
在上文中的tld文件中增加一个tag标签,内容如下
1 <!-- 动态属性标签 --> 2 <tag> 3 <name>dynimicAttr</name> 4 <tag-class>com.dev.sen.DynaAttributesTag</tag-class> 5 <body-content>empty</body-content> 6 <!-- 设置支持动态属性 --> 7 <dynamic-attributes>true</dynamic-attributes> 8 </tag>
使用标签
Jsp2的自定义方法
开发函数处理类
开发函数处理类:函数处理类就是普通类,这个普通类中包含若干个静态方法,每个静态方法都可以定义成函数。实际上这个步骤也可省略——完全可以直接用JDK或者其他项目提供的类,只要这个类包含静态方法即可
1 package com.dev.tld; 2 /** 3 * 自定义标签方法 4 * @author WangSen 5 * @date 2014-6-29 6 * @time 下午8:09:52 7 */ 8 public class Functions { 9 /** 10 * 字符翻转 11 * @param text 传入的字符串 12 * @return 翻转后的字符串 13 */ 14 public static String reverse(String text){ 15 return new StringBuffer(text).reverse().toString(); 16 } 17 18 /** 19 * 统计字串的长度 20 * @param text 待统计的字符串 21 * @return 带统计字符的长度 22 */ 23 public static int CountChar(String text){ 24 return text.length(); 25 } 26 27 }
使用标签库定义函数
定义函数的方法和定义标签类似,在<taglib…/>元素下增加<tag../>元素用于定义自定义标签;增加<function…>元素用于自定义函数,每个<function…/>只要三个子元素即可。
- name :指定自定义函数函数名;
- function-class :指定自定义函数处理类;
- function-signature :指定自定义函数对应的
在上文中的标签库定义文件中<taglib.>下追加方法的定义
1 <!-- 自定义函数 --> 2 <function> 3 <name>reverse</name> 4 <function-class>com.dev.tld.Functions</function-class> 5 <function-signature>java.lang.String reverse(java.lang.String)</function-signature> 6 </function> 7 <function> 8 <name>countChar</name> 9 <function-class>com.dev.tld.Functions</function-class> 10 <function-signature>int countChar(java.lang.String)</function-signature> 11 </function>
在jsp页面中的EL中使用函数
需要先导入标签库,然后再使用函数。如下