JSP 自定义标签 ( SimpleTagSupport )
一般情况下 JSP 内置的标签和 JSTL 里的标签已经够用了,很少有场景需要自定义 JSP 标签了
但有的时候,就是需要自己去自定义一个 JSP 标签
自定义标签
自定义标签是用户定义的 JSP 语言元素
当 JSP 页面包含一个自定义标签时将被转化为 Servlet,标签转化为对被称为 tag handler的对象的操作,即当 Sservlet 执行时 Web container 调用那些操作
JSP 标签扩展可以让我们创建新的标签并且可以直接插入到一个 JSP 页面
JSP 2.0 规范中引入 Simple Tag Handlers 来编写这些自定义标签
我们可以继承 SimpleTagSupport 类并重写 doTag() 方法来开发一个最简单的自定义标签
创建 "Hello" 标签
接下来我们自定义一个叫做 <ex:Hello>
的标签
标签语法为:
<ex:Hello />
创建自定义的 JSP标签,首先需要创建处理标签的 Java 类
因此,我们创建一个 HelloTag 类
// author: 简单教程(www.twle.cn) // Copyright © 2015-2065 www.twle.cn. All rights reserved. package cn.twle.demo; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import java.io.*; public class HelloTag extends SimpleTagSupport { public void doTag() throws JspException, IOException { JspWriter out = getJspContext().getOut(); out.println("Hello Custom Tag!<br/>"); out.println("Nice to see you,简单教程"); } }
我们重写了 doTag() 方法,并使用 getJspContext()方法获取当前的 JspContext 对象,然后将 " Hello Custom Tag!" 等字符串传递给 JspWriter 对象
编译上面的类,并将其复制到环境变量 CLASSPATH 目录中
最后,创建如下标签库
webapp\WEB-INF\custom.tld
<taglib> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>Example TLD</short-name> <tag> <name>Hello</name> <tag-class>cn.twle.demo.HelloTag</tag-class> <body-content>empty</body-content> </tag> </taglib>
然后我们就可以在 JSP 文件中使用 Hello 标签了
webapp/custom_tag.jsp
<%@ taglib prefix="ex" uri="WEB-INF/custom.tld" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <meta charset="utf-8"/> <title>JSP 自定义标签 | JSP 基础教程 | 简单教程(www.twle.cn)</title> <p>一个简单的自定义标签</p> <p><ex:Hello/></p> <br/> <p>JSP 自定义标签 | JSP 基础教程 | 简单教程(www.twle.cn)</p> <br/> <br/>
如果编译的时候提示
程序包javax.servlet.jsp.tagext不存在
可以通过 https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api 下载
在浏览器上输入 http://localhost:8080/jsp/custom_tag.jsp 显示结果如下
访问标签体
如果我们想让 <ex:Hello/>
像 JSP 标准标签库一样可以包含消息内容
<ex:Hello>Nice to see you, JSP</ex:Hello>
可以修改 HelloTag 类接收传递内容
package com.twle; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import java.io.*; public class HelloTag extends SimpleTagSupport { StringWriter sw = new StringWriter(); public void doTag() throws JspException, IOException { getJspBody().invoke(sw); getJspContext().getOut().println(sw.toString()); } }
然后再修改 customer.tld 文件
<taglib> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>Example TLD</short-name> <tag> <name>Hello</name> <tag-class>cn.twle.demo.HelloTag</tag-class> <body-content>scriptless</body-content> </tag> </taglib>
现在,<ex:Hello>
就会向我们想的那样工作了
<%@ taglib prefix="ex" uri="WEB-INF/custom.tld" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <meta charset="utf-8"/> <title>JSP 自定义标签 | JSP 基础教程 | 简单教程(www.twle.cn)</title> <p>一个简单的自定义标签</p> <p><ex:Hello>Nice to see you,简单教程</ex:Hello></p> <p>JSP 自定义标签 | JSP 基础教程 | 简单教程(www.twle.cn)</p>
在浏览器上输入 http://localhost:8080/jsp/custom_tag.jsp 显示结果如下
自定义标签属性
是不是还差点什么呢? 对,我们的 <ex:Hello>
不能设置属性
接下来我们做一些修改让 <ex:Hello>
可以设置各种属性
要接收属性,值自定义标签类必须实现 setter 方法
还是修改 HelloTag 类
// author: 简单教程(www.twle.cn) // Copyright © 2015-2065 www.twle.cn. All rights reserved. package cn.twle.demo; import javax.servlet.jsp.tagext.*; import javax.servlet.jsp.*; import java.io.*; public class HelloTag extends SimpleTagSupport { private String message; public void setMessage(String msg) { this.message = msg; } StringWriter sw = new StringWriter(); public void doTag() throws JspException, IOException { if (message != null) { /* 从属性中使用消息 */ JspWriter out = getJspContext().getOut(); out.println( message ); } else { /* 从内容体中使用消息 */ getJspBody().invoke(sw); getJspContext().getOut().println(sw.toString()); } } }
属性的名称是"message",所以 setter 方法是的 setMessage()
接在再修改下 custom.tld 文件使用 <attribute>
元素添加 "message" 属性
<taglib> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>Example TLD</short-name> <tag> <name>Hello</name> <tag-class>cn.twle.demo.HelloTag</tag-class> <body-content>scriptless</body-content> <attribute> <name>message</name> </attribute> </tag> </taglib>
好了,我们的 <ex:Hello>
可以设置属性了
<%@ taglib prefix="ex" uri="WEB-INF/custom.tld" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <meta charset="utf-8"/> <title>JSP 自定义标签 | JSP 基础教程 | 简单教程(www.twle.cn)</title> <p>一个简单的自定义标签</p> <p><ex:Hello message="Hello 简单教程">Nice to see you,简单教程</ex:Hello></p> <p>JSP 自定义标签 | JSP 基础教程 | 简单教程(www.twle.cn)</p>
我们的 <ex:Hello>
标签在既传入内容又传入属性的情况下会优先使用属性
在浏览器上输入 http://localhost:8080/jsp/custom_tag.jsp 显示结果如下
我们还可以给 custom.tld
文件还可以设置以下属性
属性 | 描述 |
---|---|
name | 定义属性的名称。每个标签的是属性名称必须是唯一的。 |
required | 指定属性是否是必须的或者可选的,如果设置为false为可选。 |
rtexprvalue | 声明在运行表达式时,标签属性是否有效。 |
type | 定义该属性的Java类类型 。默认指定为String |
description | 描述信息 |
fragment | 如果声明了该属性,属性值将被视为一个JspFragment。 |
以下是指定相关的属性实例:
..... <attribute> <name>attribute_name</name> <required>false</required> <type>java.util.Date</type> <fragment>false</fragment> </attribute> .....
如果使用了两个属性,修改 TLD 文件
..... <attribute> <name>attribute_name1</name> <required>false</required> <type>java.util.Boolean</type> <fragment>false</fragment> </attribute> <attribute> <name>attribute_name2</name> <required>true</required> <type>java.util.Date</type> </attribute> .....