JSP中自定义标签
照例,先讲理论凑字数。自定义标签实现要继承特定的类或实现特定的接口,在运行时,容器将自定义的标签转化为这些Java代码,以实现预定义的功能。
所涉及的类和接口都在javax.servlet.jsp.tagext中:
JspTag接口:作为标签的基类,起组织结构的作用。是SimpleTag和Tag的父接口。
Tag接口:定义了JSP页面与实现类之间的基本协议, JSP中标签基本的生命周期,但它不去定义一个标签真正的行为。
SimpleTag接口:定义了一个doTag的方法,是处理标签的主体内容,doTag方法会且只会被高度程序调用一次。它还定义了一些对父标签,标签体处理的方法。
SimpleTagSupport类:它提供了对SimpleTag接口的实现,它已经将处理调度的方法实现,但是在doTag方法中却是空的实现,也就是说我们要自定义标签只要继承此类,并重写它的doTag方法,就可以实现自己需要的功能。这个类中还定义了getJspContext方法,它的返回值为一个JspContext对象,我们可以将其强转为PageContext对象,从而可以得到Jsp中定义的所有隐式对象。
上面讲了几次标签的高度,看下面图
要说明的是,每次都对标签处理类进行实例化,即对每一个标签处理都会有一个对应的实例,所以不会出现线程安全问题。
下面举例说明使用继承SimpleTagSupport类的方法实现自定义标签。
实现自定义标签分为四步:
1. 创建自定义标签类,重写doTag方法来实现自己需要的功能。
2. 在WEB-INF下对新标签进行配置。
3. 在要使用标签的JSP页面使用taglib指令导入要使用的标签库
4. 在需要的地方使用标签
不带标签体,不带属性的标签,显示用户IP。1. 创建自定义标签类
package com.heima.tags;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class ShowIp extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
// 得到JspContext,强转为PageContext类型,可以得到其它的JSP对象
PageContext pc = (PageContext) getJspContext();
String addr = pc.getRequest().getRemoteAddr();
// 得到输出流
JspWriter out = pc.getOut();
out.write(addr);
}
}
2. 在WEB-INF下对新标签进行配置。
<?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.0</tlib-version>
<!-- 在JSP中使用的前缀,在taglib指令中的prefix属性使用 -->
<short-name>hm</short-name>
<!-- 在JSP中的名,在taglib指令中的uri属性使用 -->
<uri>http://chang.zhi.qiang/tags/tags</uri>
<tag>
<!-- 标签的名称 -->
<name>showIp</name>
<!-- 自定义标签类的名称 -->
<tag-class>com.heima.tags.ShowIp</tag-class>
<!-- 没有标签体 -->
<body-content>empty</body-content>
</tag>
<tag>
<name>show</name>
<tag-class>com.heima.tags.LoopShow</tag-class>
<!-- 可以有不带脚本的标签体 -->
<body-content>scriptless</body-content>
<!-- 配置属性 -->
<attribute>
<!-- 属性名称 -->
<name>count</name>
<required>true</required>
</attribute>
</tag>
</taglib>
3. 在要使用标签的JSP页面使用taglib指令导入要使用的标签库
<%@ taglib uri="http://chang.zhi.qiang/tags/tags" prefix="hm" %>
4. 在需要的地方使用标签
<hm:showIp/>
这样就完成了对一个没有标签体的自定义标签的定义和使用。
其中的<body-content></tody-content>可以使用下面几个参数。
1. empty:标签体为空,不能有内容
2. scriptless:可以使用模板元素,EL表达式,还可以是定制和标准动作,但是不能是脚本。
3. tagdependent:纯文本内容,不计算EL表达式也不会对发出动作等。
4. JSP:能放JSP中所有的元素。
带标签休,带属性的标签,循环显示标签体内容,次数由属性决定。
自定义类
package com.heima.tags;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class LoopShow extends SimpleTagSupport {
private int count;
public void setCount(int count) {
this.count = count;
}
@Override
public void doTag() throws JspException, IOException {
for (int i = 0; i < count; i++) {
getJspBody().invoke(null);
}
}
}
配置和引用都在上一个例子中完成,使用方法也与上一个类似:
<hm:show count="3">abcd</hm:show>
说明:可以在类中可以定义成员而不用担心线程安全问题。对成员设定公开的set方法,容器会自动调用set方法将标签的值传递给对应的成员。