开发一个简单的自定义标签分三步:
1、创建一个普通的 Java 类,继承 SimpleTagSupport 类,叫做 标签处理器类:
package com.customtag.demo;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
自定义一个标签处理器类:
1、继承 SimpleTagSupport 类;
2、覆盖 doTag 方法,编写功能代码;
*/
public class CustomTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
// 获取系统当前时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(new Date());
// 获取 JspContext 对象,并将其转换成 PageContext 对象
PageContext pageContext = (PageContext)this.getJspContext();
// 通过 pageContext 对象可以获取到 jsp 的其他八个内置对象
JspWriter out = pageContext.getOut();
// 将当前时间输出到浏览器
out.write(date);
}
}
2、在 web 项目的 WEB-INF 目录下创建一个 .tld 文件(比如 custom.tld),这个 tld 文件叫做 标签库的声明文件;(参考核心标签库的 c.tld 文件)。web 项目启动的时候,服务器会加载 WEB-INF 下的所有文件,比如 web.xml。
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.1</tlib-version> <!-- 标签库的版本 -->
<short-name>custom</short-name> <!-- 标签库前缀(<%@taglib> 指令中 prefix 的值) -->
<uri>http://com.customtag.demo.CustomTag</uri> <!-- tld 文件的唯一资源标记(<%@taglib> 指令中 uri 的值) -->
<!-- 声明一个标签 -->
<tag>
<name>showDate</name> <!-- 标签的名字 -->
<tag-class>com.customtag.demo.CustomTag</tag-class> <!-- 标签处理器类的全名(含包名) -->
<!--
输出标签体内容格式:
scriptless:标签体不可以写 jsp 的 java 代码;
JSP:在传统标签中使用的,可以写和执行 jsp 的 java 代码;
empty:必须是空标签;
tagdependent:标签体内容可以写 jsp 的 java 代码,但不会执行;
-->
<body-content>scriptless</body-content>
</tag>
</taglib>
3、在 jsp 页面(07_custom.jsp)中导入 自定义标签库并使用;
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="custom" uri="http://com.customtag.demo.CustomTag" %> <%-- 导入自定义标签库 --%>
<html>
<head>
<title>自定义标签</title>
</head>
<body>
<%
// 获取当前时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(new Date());
// 输出到浏览器
out.write("当前时间:" + date);
%>
<%-- 上面的功能 用现有的标签无法实现,可以通过自定义标签实现 --%>
<hr>
<%-- 使用自定义标签实现上面的功能,在浏览器输出当前时间 --%>
用自定义标签输出的当前时间:<custom:showDate />
</body>
</html>
输出结果:
自定义标签的 五个 功能细节:
1、输出标签体内容 :默认情况下不会输出 标签体内容,需要在 doTag 方法中手动设置输出标签体内容;
public class CustomTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
System.out.println("执行了自定义标签");
/*
输出标签体内容(默认情况下不会输出标签体内容)
* */
// 1、得到封装 标签体内容 的对象
JspFragment jspBody = this.getJspBody();
// 2、得到 JspWriter 对象
JspWriter out = this.getJspContext().getOut();
// 3、执行 invoke 方法,把标签体内容输出到指定的 Writer 对象中,
// Writer 对象就会自动把标签体内容输出到浏览器;
jspBody.invoke(out);
// 当 Writer 为 null 时,默认情况下也是向浏览器输出内容
// jspBody.invoke(null); // 这一行代码可以代替上面 2、3 两步的代码
}
}
2、禁止执行标签后面的代码(默认情况下,标签后面的内容会继续执行)
public class CustomTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
System.out.println("执行了自定义标签");
/*
禁止执行标签后面的内容(默认情况下会执行)
抛出 SkipPageException 异常,标签后面的代码都不会执行了;
* */
throw new SkipPageException();
}
}
3、重复输出标签体内容:
public class CustomTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
System.out.println("执行了自定义标签");
// 得到封装 标签体内容 的对象
JspFragment jspBody = this.getJspBody();
// 控制重复输出标签体内容:调用几次 jspBody.invoke(null) 方法,就会向浏览器输出几次 标签体内容
for (int i = 0; i < 5; i++){
jspBody.invoke(null);
}
}
}
4、修改标签体内容:
java 文件:
public class CustomTag2 extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
System.out.println("执行了自定义标签");
// 得到封装 标签体内容 的对象
JspFragment jspBody = this.getJspBody();
/*
修改标签体内容
* */
// 1、创建 StringWriter 对象,作为一个缓存区存放 标签体内容
StringWriter sw = new StringWriter();
// 2、把标签体内容输出到 字符缓冲区
jspBody.invoke(sw);
// 3、从缓冲区中取出 标签体内容
String content = sw.toString();
// 4、修改标签体内容
content = content + "--- 我被修改了!";
// 5、将改变后的标签体内容输出到浏览器
this.getJspContext().getOut().write(content);
}
}
jsp 文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="custom" uri="http://com.customtag.demo.CustomTag" %>
<html>
<head>
<title>控制自定义标签体内容是否输出</title>
</head>
<body>
<custom:print>
标签体内容
</custom:print>
</body>
</html>
输出结果:
5、带属性的自定义标签:
java 文件:
public class CustomTag2 extends SimpleTagSupport {
// 1、声明属性的成员变量
private Integer num;
// 2、必须提供公开的 setter 方法,用于给属性赋值
public void setNum(Integer num){
this.num = num;
}
@Override
public void doTag() throws JspException, IOException {
System.out.println("执行了自定义标签:" + num);
}
}
tld 文件:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.1</tlib-version> <!-- 标签库的版本 -->
<short-name>custom</short-name> <!-- 标签库前缀(<%@taglib> 指令中 prefix 的值) -->
<uri>http://com.customtag.demo.CustomTag</uri> <!-- tld 文件的唯一资源标记(<%@taglib> 指令中 uri 的值) -->
<tag>
<name>print</name>
<tag-class>com.customtag.demo.CustomTag2</tag-class>
<body-content>scriptless</body-content>
<!-- 声明属性 -->
<attribute>
<name>num</name> <!-- 属性名称 -->
<required>true</required> <!-- 是否必填 -->
<rtexprvalue>false</rtexprvalue><!-- 是否支持 EL 表达式 -->
</attribute>
</tag>
</taglib>
jsp 文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="custom" uri="http://com.customtag.demo.CustomTag" %>
<html>
<head>
<title>控制自定义标签体内容是否输出</title>
</head>
<body>
<custom:print num="33">
标签体内容
</custom:print>
</body>
</html>
输出结果: