自定义标签
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>
转载请于明显处标明出处