自定义标签
1、标签类型
- Has body
有标签体,必须位于开始标记和结束标记之间
内容包括:自定义标记或核心标记,HTML 文本,标签依赖的主体内容
比如:<html:submit> OK </html:submit>
- Has no body
没有标签体
比如<html:errors />
2、自定义标签的步骤
- 创建一个类,用来对标签的行为进行控制
这个类 继承 javax.servlet.jsp.tagext.SimpleTagSupport 并重写 doTag() 方法
- 创建标签库描述符 ( Tag Library Descriptor ):
标签库描述符是个 XML 文件,一般被放在 WEB-INF 目录下即可
标签库描述符 的扩展名不是 .xml 而是 .tld
- 在页面上使用标签
导入标签库:uri 用于指定tld 中<uri> 中的字符串值,prefix 用于指定标签的前缀,这个名称任意取
<%@ taglib prefix = "m" uri = "http://www.ecut/tags"%>
使用标签:其中tagPrefix 要与taglib 中的prefix 的值写一致,而tagName 就是tld 文件中<tag> 内部<name> 标签内部的字符串值
<tagPrefix:tagName />
3、测试案例
- 不带属性、不带标签体 的自定义标签: HelloTag
package ecut.tags; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; /*创建一个类,用来对标签的行为进行控制 这个类 继承 javax.servlet.jsp.tagext.SimpleTagSupport 并重写 doTag() 方法*/ public class HelloTag extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { JspContext jspContext = this.getJspContext(); JspWriter out = jspContext.getOut(); // 这个方法由容器调用。 所有标签逻辑,迭代,标签体的处理等都放在这个方法中。 out.println( "<div style='border:1px solid blue;text-align:center;padding:5px 5px ;'>" ); out.println( "hello" ); out.println( "</div>" ); } }
标签库描述符m.tld
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1"> <!-- short-name建议所采用的简称(prefix),具体用那个简称以jsp页面中prefix为准 --> <!-- uri 唯一 --> <tlib-version>1.0</tlib-version> <short-name>m</short-name> <uri>http://www.ecut/tags</uri> <!-- 定义一个标签: 没有属性、不带标签体 --> <tag> <name>hello</name> <tag-class>ecut.tags.HelloTag</tag-class> <!-- 必须有body-content元素 --> <body-content>empty</body-content> </tag> </taglib>
<tag>各子元素的意义与作用
<description> 可选,标签的描述信息
<name> 必需,定义JSP页面引用的标签名称(标签后缀)
<tag-class> 必需,标识实现标签处理类的完全限定名(含包名的类名)
<body-content> 必需,告诉容器如何处理标签开始和结束之间的内容
<body-content> 取值可以是empty 、scriptless 、tagdependent 、JSP
empty : 不允许任何内容出现在标签体内(用于定义没有标签体的标签)
scriptless : 允许标签中有JSP 内容,但不能包含<% ... %> 和<%= ... %> 之类
tagdependent : 允许此标签像其主体一样有任何类型的内容
» 但是这些内容根本不会被处理,并会完全忽略
» 由标签处理类开发人员来决定访问这些内容,并对其进行处理
» 比如其中包含一个允许JSP 开发人员执行的SQL 语句
JSP : 允许在标签体中放置JSP 内容
在index.jsp上使用标签
<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%> <!-- 导入标签库 -->
<%@ taglib prefix = "m" uri = "http://www.ecut/tags"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>自定义标签</title> </head> <body> <!--使用标签 --> <m:hello></m:hello> </body> </html>
- 带有属性的自定义标签: TableTag
package ecut.tags; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; public class TableTag extends SimpleTagSupport { //getXxx()方法要和标签的属性名一致 private int rows ; private int columns ; private String className ; @Override public void doTag() throws JspException, IOException { System.out.println( "rows : " + rows ); System.out.println( "columns : " + columns ); System.out.println( "className : " + className ); JspContext jspContext = this.getJspContext(); JspWriter out = jspContext.getOut(); out.println( "<table class='" + className + "'>" ); for( int i = 0 ; i < rows ; i++ ){ out.println( "<tr>" ); for( int j = 0 ; j < columns ; j++){ out.println( "<td>" ); out.println( i + " , " + j ); out.println( "</td>" ); } out.println( "</tr>" ); } out.println( "</table>" ); } public int getRows() { return rows; } public void setRows(int rows) { this.rows = rows; } public int getColumns() { return columns; } public void setColumns(int columns) { this.columns = columns; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } }
如果自定义标签包含属性,那么对应的标签类中也要有相应的属性,getXxx名称还要完全相同,每个属性都必须有对应的getter 和setter 方法
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1"> <!-- short-name建议所采用的简称(prefix),具体用那个简称以jsp页面中prefix为准 --> <!-- uri 唯一 --> <tlib-version>1.0</tlib-version> <short-name>m</short-name> <uri>http://www.ecut/tags</uri> <!-- 定义一个带有属性不带标签体的标签 --> <tag> <name>table</name> <tag-class>ecut.tags.TableTag</tag-class> <body-content>empty</body-content> <!-- 定义标签的属性 --> <attribute> <name>rows</name> <!-- 是否必填 --> <required>true</required> <!--run time expression value 是否可以接受一个运行时值(动态的值) --> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>columns</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>className</name> <required>false</required> <rtexprvalue>false</rtexprvalue> </attribute> </tag> </taglib>
<attribute> 标签中各个子元素的意义及作用
<name> 必需,定义属性名称
严格区分大小写,与Tag Handler Class 里的getter 和setter 对应
<required> 可选,指定是必须始终提供该属性
false 是默认值,表示并不是一定要提供该属性
true 是可选值之一,表示必须始终提供该属性
<rtexprvalue> 可选,Runtime Expression Value指出属性值是一个动态确定的值还是一个固定的值
true 表示可以接受运行时的表达式的值,表达式可以是 JSP 表达式,也可以是 EL 表达式
false 表示不可以接受表达式的值,因此在使用时必须显式指定具体的值
<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%> <!-- 导入标签库 -->
<%@ taglib prefix = "m" uri = "http://www.ecut/tags"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>自定义标签</title> <style type="text/css"> .tab { border: 1px solid blue; width: 100%; margin: 20px auto; border-spacing: 10px; } .tab td { border: 1px solid green; height: 30px; text-align: center; vertical-align: middle; } </style> </head> <body> <!--使用标签 --> <m:table rows="3" columns="4" className="tab"></m:table> <% int r = 6 ; pageContext.setAttribute( "c" , 3 ) ; // page scope 中存入一个名称是 c 的值 %> <m:table rows="<%= r %>" columns="${ c }" className="tab"></m:table>
</body>
</html>
- 有属性、有身体 的标签 : ForTag
package ecut.tags; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.tagext.SimpleTagSupport; public class ForTag extends SimpleTagSupport { private int begin ; private int step ; private int end ; private String var ; @Override public void doTag() throws JspException, IOException { JspContext jspContext = this.getJspContext(); //JspWriter out = jspContext.getOut(); JspFragment fragment = this.getJspBody(); // 获得 标签体 对应的 对象 for( int i = begin ; i <= end ; i += step ){ // < var , i > System.out.println( var + " , " + i ); // 将每次循环中的 i 的值 放入到 page scope ( JspContext 是 PageContext 类的父类 ) jspContext.setAttribute( var , i ) ; // jspContext.setAttribute( "counter" , i ); // 执行 JSP 代码片段 ( 标签体 ),如果是null,则会自动将getOut()返回的值传入invoke方法中 fragment.invoke( null ); } } public int getBegin() { return begin; } public void setBegin(int begin) { this.begin = begin; } public int getStep() { return step; } public void setStep(int step) { this.step = step; } public int getEnd() { return end; } public void setEnd(int end) { this.end = end; } public String getVar() { return var; } public void setVar(String var) { this.var = var; } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1"> <!-- short-name建议所采用的简称(prefix),具体用那个简称以jsp页面中prefix为准 --> <!-- uri 唯一 --> <tlib-version>1.0</tlib-version> <short-name>m</short-name> <uri>http://www.ecut/tags</uri> <!-- 定义一个带有属性、带有标签体的标签 --> <tag> <name>for</name> <tag-class>ecut.tags.ForTag</tag-class> <body-content>scriptless</body-content> <attribute> <name>begin</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> <attribute> <name>step</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> <attribute> <name>end</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> <attribute> <name>var</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> </tag> </taglib>
<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%> <!-- 导入标签库 -->
<%@ taglib prefix = "m" uri = "http://www.ecut/tags"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>自定义标签</title> </head> <body>
<m:for begin="10" step="10" end="100" var="counter"> <div>${ counter }</div> </m:for>
</body>
</html>
转载请于明显处标明出处