您的位置:首页 > Web前端 > JavaScript

jsp自定义标签

2017-11-08 11:26 155 查看
一、概述
JSP 2.0 中提供了两种新的开发自定义标记的方法:
1、简单标签机制SimpleTag
JSP 2.0 中加入了新的创建自定义标记的API:javax.servlet.jsp.tagext.SimpleTag,该API 定义了用来实现简单标记的接口。和JSP 1.2 中的已有接口不同的是,SimpleTag 接口不使用doStartTag()和doEndTag()方法,而提供了一个简单的doTag()方法。这个方法在调用该标记时只被使用一次。一个自定义标记中实现的所有逻辑都在这个方法中实现。相对JSP1.2 中自定义标记机制,SimpleTag 的方法和处理周期要简单得多。
注意:SimpleTag接口:只提供了一个doTag()方法,在这个方法中实现标记的所有逻辑。
2、 标签文件
标签文件允许JSP 网页作者使用JSP 语法创建可复用的标签库。标签文件的扩展名必须是.tag。
注意:网页引用标签文件,文件扩展名必须是.tag

1.1 使用简单标签机制
与JSP1.2 相似,开发自定义标签要遵循“开发标记类---配置TLD 文件----在JSP 中使用”的过程,
示例如下:
步骤一:编写标记处理类AddTag.java
package tag;
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 AddTag extends SimpleTagSupport{
private int num1 = 0;
private int num2 = 0;
public void setNum1(int num1) {
this.num1 = num1;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public void doTag() throws JspException, IOException {
JspContext ctx = getJspContext();
JspWriter out = ctx.getOut();
int sun = num1+num2;
out.print(num1+"+"+num2+"="+sun);
}
}

步骤二:编写描述符文件 test.tld:放在/WEB-INF/test-tld/test.tld下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib> <!-- 标签定义成<test:add
/> -->
<tlibversion>1.0</tlibversion>
<jspversion>1.2</jspversion>
<shortname>test</shortname> <!-- 这个test可以设置为空,你标签就可以定义成<add
/>了,不过一般比较常见的都是<test:add />这种类型的 -->
<tag>
<name>add</name>
<tagclass>tag.AddTag</tagclass>
<bodycontent>empty</bodycontent> <!-- 就是<test:add
></test>中间的内容是空的 -->
<info>Add Tag</info>
<attribute>
<name>num1</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>num2</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>

步骤三:在JSP 中使用标记:
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="test" uri="/WEB-INF/test-tld/test.tld" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>测试自定义标签</title>
</head>
<body>
SimpleTag 测试:<br />
<h1><test:add num1="2" num2="3"/> </h1>
</body>
</html>

无需在web.xml下配置,
运行结果如下:



1.2 使用标签文件
通过标签文件实际上可以将一个JSP 文件的内容作为标签处理程序,但该文件扩展名必须是.tag,
示例如下:
1) 标记文件hello.tag,该文件存放在 WEB-INF/tags 目录下
hello.tag.<br>
IP:<%= request.getRemoteAddr() %>
2) 在JSP 中使用tag 文件
<%@ page contentType="text/html;charset=gb2312" %>
<%@ taglib prefix="test" tagdir="/WEB-INF/tags/" %>
<h2>Tag File 测试</h2>
<test:hello/>
3) 运行效果如下:



二 、自定义标签简介

2.1 自定义标签概念
JSP 自定义标记为在动态Web 页中将表示与业务逻辑分离提供了一种标准化的机制,使页面设计者可以将注意力放到表示上,而应用程序开发人员编写后端的代码。
注意:自定义标记可以在后台完成某些操作,而HTML 标记只能完成前台显示的功能,自定义标签的使用方法和标准HTML标签使用方法一样。

2.2 标签相关概念
JSP 自定义标签的使用语法与普通HTML标签相同,与自定义标签相关的基本术语简单说明如下,
这些术语在开发JSP 自定义标签时要用到:
1) 自结束标签——没有标记体的标签
示例:<test:myhrtag />
说明:假设myhrtag 是一个自定义标签
2) 属性
示例:<test:myhrtag color=”red” />
说明:以上标签中包含了color 属性,值为red
3) 带标记体的标签
示例:<test:myhrtag > xxxxx </test:myhrtag>
说明:以上标签中间的xxxxx 即为标记体
4) 子标记
示例: <test:myhrtag >
<test:mytag2/>
</test:myhrtag>
说明:以上myhrtag 标签中间的mytag2 即为子标记

2.3 如何创建自定义标签

自定义标签功能的实现要求在后台必须有一个相关的JAVA 类的支持,但并不是任意编写一个JAVA 类就能处理JSP 标签,这个类也必须实现指定的规范才能用于支持JSP 标签,这些规范表现形式也是接口和类,它们在javax.servlet.jsp.tagext包中声明,主要接口/类的描述如下:
javax.servlet.jsp.tagext.Tag 接口,所有处理JSP 标签的类必须实现该接口。该接口中声明了6个方法,如果直接从该接口生成类则必须实现所有的6 个方法,通常不会直接通过该接口生成标签的处理类。
javax.servlet.jsp.tagext.TagSupport 类,该类实现了Tag 接口,用于创建不带标记体的自结束标签,这些标签中可以带属性。
javax.servlet.jsp.tagext.BodyTagSupport 类,该类继承了TagSupport,用于创建带标记体的标签。
通常我们自定义
19953
的标签,编写处理程序时使用TagSupport 和BodyTagSupport 即可,不需要涉及到标签体的,继承TagSupport,需要用标签体的,用BodyTagSupport,以下是开发和使用一个JSP 自定义标签的全过程:

1) 开发标记处理类,编译生成class 文件,该类要继承TagSupport 或BodyTagSupport;
2) 创建标记库描述符文件*.tld,在该文件中为标记处理类指定标签名、声明标签属性;
3) 在JSP 中引用标签库;
4) 在JSP 中使用标JSP 标签

三、自结束标签(不带标签体,TagSupport)
3.1 自结束标签简介
这是一种不带标记体的标签,所以该类标签的处理类直接继承javax.servlet.jsp.tagext.TagSupport即可。
TagSupport 的主要方法如下:
public int doStartTag() throws JspException //该方法实现是可选的,不实现该方法:当遇到开始标签时,什么都不做。
在WEB 容器遇到标签开始时,该方法会运行。
public int doEndTag() throws JspException
在WEB 容器遇到标签结束时,该方法会运行。

(一)PageContext类
TagSupport 类中有一个重要的成员:pageContext,该成员的功能与JSP 的内置对象pageContex完全相同。通过该对象可以得到其他几个JSP 对象的引用。这样,我们就可以在JAVA 类中与JSP 进行交互了。如: JspWriter
out=pageContext.getOut();这一语句可以得到JSP 内置对象out 的引用,通过out 我们就可以向客户端浏览器中输出内容了。要使用其他几个JSP 对象原理与此相同。


pageContext是javax.servlet.jsp.PageContext类的实例对象,可以使用PageContext类的方法。
实际上,pageContext对象提供了对JSP页面所有的对象及命名空间的访问,正如前面所介绍的一样,
使用pageContext对象可以访问application对象、exception对象,还有session对象等。
pageContext对象的方法可以访问除本身以外的8个JSP内部对象,还可以直接访问绑定在application对象、page对象、
request对象、session对象上的Java对象。pageContext对象相当于JSP程序中所有对象功能的集成者。
不过,这里存在着一个问题,既然可以直接访问JSP内部对象,为什么还要多此一举,通过pageContext对象来访问它们呢?

getOut()
该方法返回一个JspWriter类的实例对象,也就是JSP内置对象——out对象,可以往客户端写入输入流。
<%
JspWriter myout=pageContext.getOut();


myout.println(“myout write: hello world”+”<br>”);
out.println(“out write: hello world”);

//或者使用write(String str)方法

%>

3.2 自结束标签开发示例

方式二:动态引用
步骤一:编写标记处理类
package tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;

/**
* 自定义自结束标签,不含标签体。
*
* 1、在自定义的类中,重写了父类TagSupport 的两个方法:doStartTag()、doEndTag(),在容器遇到标记开始时会运行doStartTag(),遇到标记结束时运行doEndTag()方法;
* 2、doStartTag()方法的返回值:通常可以取两个值:
* EVAL_BODY_INCLUDE——包含标记体,本例中要编写自结束标记所以不使用该值;
* SKIP_BODY——跳过标记体,即不处理标记体,开发自结束标记应该使用该值。

* 3、doEndTag()方法的返回值:通常可以取两个值:
* SKIP_PAGE——返回这个值,则终止页面执行;
* EVAL_PAGE——返回该值则处理完当前标记后,JSP 页面中止运行。
*/

public class MyHrTag extends TagSupport{

/**
*
*/
private static final long serialVersionUID =
1L;

/*
* 在WEB 容器遇到标签开始时,该方法会运行。
* 该方法可以自行定义,也可以不定义。不定义该方法则遇到开始标签什么都不做
* */
public int doStartTag() throws JspException
{
try {
//得到网络输出流,pageContext 是从父类继承过来的成员
JspWriter out = pageContext.getOut();
//向网页输出内容
out.println("<h4>开始执行doStartTag()......</h4>");
//输出5 条水平线;
for(int i=1;
i<=5; i++){
out.println("<hr>");
}
} catch (Exception e) {
e.printStackTrace();
}
//return EVAL_BODY_INCLUDE; //处理标记体
return Tag.SKIP_BODY; //跳过标记体;
}

/*
* 在WEB 容器遇到标签结束时,该方法会运行。
* 该方法可以自行定义,也可以不定义。不定义该方法则遇到结束标签什么都不做
* */
public int doEndTag() throws JspException
{
try {
JspWriter out=pageContext.getOut();
out.println("<h3>开始执行doEndTag().....</h3>.");
} catch (Exception e) {
e.printStackTrace();
}
//return Tag.SKIP_PAGE; //返回这个值,则终止页面执行;
return EVAL_PAGE;
}
}

步骤二:创建标记库描述符文件myhr.tld,该文件要存放在 WEB-INF/test-tld 目录下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<!--
解释:
在tld 文件中,映射了标记名和处理程序类;
<tallib>元素,代表开始一个标记库的描述
<tligversion>元素,代表标记库的版本
<jspversion>元素,代表标记所支持的JSP 的版本
<shortname>为标记库起别名,相当于注释,无实际用途
<tag>元素,代表开始描述一个标记,其下子元素如下:
<name>——为标记处理类起的标记名
<tagclass>——指定标记处理类的全名(即带包的名字)
<bodycontent>——标记体的类型,该示例中不需要标记体,所有设置为EMPTY,该值的其他取值在后续内容中讲解
-->
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>myhr</shortname> <!-- 标签以<myhr:XXX
/>形式 -->
<tag>
<name>MyHr</name> <!-- 该标签为<myhr:MyHr
/> -->
<tagclass>tag.MyHrTag</tagclass>
<bodycontent>EMPTY</bodycontent>
</tag>
</taglib>

步骤三:在JSP 中引用标记库描述文件
引用标记库有两种方式,分别称为静态引用和动态引用。
方式一:动态引用(即直接在JSP 页面中使用TLD 文件)
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="/WEB-INF/test-tld/myhr.tld" prefix="myhr" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'MyHr1.jsp' starting page</title>
</head>
<body>
<myhr:MyHr/>
</body>
</html>

JSP 指令<%@ taglib... %>用于引用标记库,该指令的两个属性作用如下:
uri——指明要引用的标记库,在静态引用中就是TLD 文件的路径
prefix——为标记起的前缀名,可以防止多个标记重名的情况出现

方式二:静态引用
首先在web.xml 中为TLD 文件声明别名:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<Web-app>
……
<taglib>
<taglib-uri>myhr2</taglib-uri>
<taglib-location>/WEB-INF/myhr.tld</taglib-location>
</taglib>
……
</Web-app>
然后在JSP 中通过别名引用TLD 文件:
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="myhr2" prefix="myhr" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'MyHr1.jsp' starting page</title>
</head>
<body>
<myhr:MyHr/>
</body>
</html>
到此为止,自结束标签开发完毕,其中主要工作有两个:开发标记处理类、配置TLD 文件。访
问JSP,运行结果如下:



四、标签中的属性
4.1 为自定义标签添加属性
以上的示例中开发了一个简单的JSP 标签,但一个实用的标签通常还要由属性来制定标签的特定行为,以下示例演示为自定义标签添加属性。该示例在1.2 示例基础上,为标签添加了color 和loop两个自定义属性,以控制水平线的颜色和输出的水平线的数量。
步骤一:编写标记处理类
package tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;

/**
*
* 该类为自定义标签添加了两个属性,属性的声明与javabean 语法完全相同,即属性本身是private 类型,
* 但要求提供public 的get、set 方法。
*
*/

public class MyHrTag2 extends TagSupport{

//声明属性
private String color = "black"; //定义线条颜色
private String loop = "1"; //定义输出水平线的条数

//严格按照javabean模式
public void setColor(String
color) {
this.color = color;
}

//严格按照javabean模式
public void setLoop(String
loop) {
this.loop = loop;
}

//只定义遇到开始标签执行方法即可了。
public int doStartTag() throws JspException
{
try {
//得到网络输出流
JspWriter out = pageContext.getOut();
//向网页输出内容;
out.println("<h4>开始执行doStartTag()......</h4>");
int n = Integer.parseInt(loop);
for (int i=1;i<=n;i++)
{
out.print("<hr color='"+this.color+"'
/>");
}
} catch (Exception e) {
e.printStackTrace();
}
return Tag.SKIP_BODY;
}

}

步骤二:创建TLD 文件,本例中是在1.2 中的myhr.tld 文件中进行修改得到:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<!--
解释:
在tld 文件中,映射了标记名和处理程序类;
<tallib>元素,代表开始一个标记库的描述
<tligversion>元素,代表标记库的版本
<jspversion>元素,代表标记所支持的JSP 的版本
<shortname>为标记库起别名,相当于注释,无实际用途
<tag>元素,代表开始描述一个标记,其下子元素如下:
<name>——为标记处理类起的标记名
<tagclass>——指定标记处理类的全名(即带包的名字)
<bodycontent>——标记体的类型,该示例中不需要标记体,所有设置为EMPTY,该值的其他取值在后续内容中讲解
<tag>中的子元素
<attribute>用于为标签声明属性,其子元素如下:
<name>——用于指定属性名称
<required>——用于声明该属性是否为必需的,本例中声明color、loop 两个属性都不是必需的。
-->
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>myhr</shortname> <!-- 标签以<myhr:XXX
/>形式 -->
<tag>
<name>MyHr</name> <!-- 该标签为<myhr:MyHr
/> -->
<tagclass>tag.MyHrTag</tagclass>
<bodycontent>EMPTY</bodycontent>
</tag>
<tag>
<name>MyHr2</name> <!-- 该标签为<myhr:MyHr
/> -->
<tagclass>tag.MyHrTag2</tagclass>
<bodycontent>EMPTY</bodycontent>
<attribute>
<name>color</name>
<required>false</required>
</attribute>
<attribute>
<name>loop</name>
<required>false</required>
</attribute>
</tag>
</taglib>

步骤三:在JSP 中引用TLD,并使用标签
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="/WEB-INF/test-tld/myhr.tld" prefix="myhr" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'MyHr3.jsp' starting page</title>
</head>
<body>
第一次测试(未赋属性值):<br>
<myhr:MyHr2/>

第二次测试(使用两个属性):<br>
<myhr:MyHr2 color="red" loop="3"/>

第三次测试(使用一个属性):<br>
<myhr:MyHr2 color="blue"/>

测试完毕.
</body>
</html>

运行图



4.2 标签综合示例
该示例中创建了一个JSP 标签,用于在JSP 中判断用户是否登录过,如果没登录过则自动转到登录页,这样就可以避免在JSP 中使用代码段进行业务判断了。
第一步:定义标签类LoginTag.java,为标记处理程序,从session 中取出登录标志进行判断用户是否登录过:
package tag;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;

public class LoginTag extends TagSupport{

public int doStartTag() throws JspException
{
try {
HttpSession session = pageContext.getSession();
Object obj = session.getAttribute("User");
//判断是否从未登录过,如果没登录过则转到登录页;
if(obj==null){
((HttpServletResponse)pageContext.getResponse()).sendRedirect("login.html");
return SKIP_BODY;
}
} catch (Exception e) {
e.printStackTrace();
}
return Tag.SKIP_BODY;
}
}

第二步:编写login.tld
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<!--
解释:
在tld 文件中,映射了标记名和处理程序类;
<tallib>元素,代表开始一个标记库的描述
<tligversion>元素,代表标记库的版本
<jspversion>元素,代表标记所支持的JSP 的版本
<shortname>为标记库起别名,相当于注释,无实际用途
<tag>元素,代表开始描述一个标记,其下子元素如下:
<name>——为标记处理类起的标记名
<tagclass>——指定标记处理类的全名(即带包的名字)
<bodycontent>——标记体的类型,该示例中不需要标记体,所有设置为EMPTY,该值的其他取值在后续内容中讲解
<tag>中的子元素
<attribute>用于为标签声明属性,其子元素如下:
<name>——用于指定属性名称
<required>——用于声明该属性是否为必需的,本例中声明color、loop 两个属性都不是必需的。
-->
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>test</shortname> <!-- 标签以<myhr:XXX
/>形式 -->
<tag>
<name>islogin</name> <!-- 该标签为<myhr:MyHr
/> -->
<tagclass>tag.LoginTag</tagclass>
<bodycontent>EMPTY</bodycontent>
</tag>
</taglib>

第三步:动态调用标签
部分内容如下:
<%@ page language="java" contentType="text/html;charset=GB2312"%>
<%@ taglib uri="/WEB-INF/myhr.tld" prefix="test" %>
….
<test:islogin/>
<h3>欢迎</h3>
….

4.3 TLD 文件概述
以上示例中创建了标记描述符文件*.TLD,现总结该文件的用法如下:
该文件必须放在 WEB-INF 目录下;
该文件是XML 格式的文件,各元素及功能说明如下:
元素 说明
<taglib> 代表开始一个标记库的描述
<tlibversion> 代表标记库的版本,是自定义的
<jspversion> 代表标记所支持的JSP 的版本
<shortname> 为标记库起别名,相当于注释,无实际用途
<tag> 代表开始描述一个标记
表11-1 标记描述符TLD 文件元素说明
其中<tag>元素中又包含若干子元素,说明如下:
元素 说明
<name> 为标记处理类起的标记名
<tagclass> 指定标记处理类的全名(即带包的名字)
<bodycontent> 标记体的内容类型,如果为EMPTY 代表无标记体
<attribute> 用于为标签声明属性
表11-2 <tag>元素的子元素
<attribute>元素为标签声明属性时,需要两个子元素:
<name> 用于指定属性名称
<required> 用于声明该属性是否为必需的

五、标签中的标记体
5.1 标记体简介
标签的标记体是 JSP 页中出现在自定义标签的开始和结束标签之间的数据,标记体也称正文。操纵其正文的标签称为带标记体的标签(也称为正文标签)。
可以编写标签处理程序对标签的标记体进行操作。要编写标记体标签处理程序,必须实现BodyTag 接口。BodyTag 继承了Tag 的所有方法,而且还实现了另外两个处理正文内容的方法,见下表:
方法 说明
setBodyContent(BodyContent b) bodyContent 属性的 Setter 方法
doInitBody() 对正文内容进行初始化操作

为方便开发,在JSP 类库中为BodyTag 接口提供了实现类:javax.servlet.jsp.tagext.BodyTagSupport。该类继承了TagSupport 并实现了BodyTag 接口。因此,标记体标签处理程序只需要覆盖要使用的方法。BodyTagSupport 类中定义了一个protected bodyContent 成员变量及get/setBodyContent()方法,bodyContent 是一个缓冲区,用以保存标记体正文内容。
在一个标签处理类中,BodyTag 的处理流程如下:
1、当容器创建一个新的标签实例后,通过setPageContext 来设置标签的页面上下文。
2、使用setParent 方法设置这个标签的上一级标签,如果没有上一级嵌套,设置为null。
3、设置标签的属性,如果没有定义属性,就不调用此类方法。
4、调用doStartTag 方法,这个方法可以返回以下三者之一:EVAL_BODY_INCLUDE、
EVAL_BODY_BUFFERED、SKIP_BODY,当返回EVAL_BODY_INCLUDE 时,就将标记
体直接写到输出流中,如果返回SKIP_BODY,就不再计算标签的正文,如果返回EVAL_BODY_BUFFERED,就将标记体的正文包含到bodyContent 成员中。
5、调用setBodyContent 设置当前的BodyContent.
6、调用doInitBody,可以在该方法中对BodyContent 进行一些初始化操作.每次计算完Body 后调用doAfterBody,如果返回EVAL_BODY_AGAIN,表示继续处理一次标记体,直到返回SKIP_BODY 才继续往下执行.
7、调用doEndTag 方法,结束标签处理.

5.2 一个简单的带标记体的标签

本示例中创建了一个标签用于在浏览器中输出其标记体内容,且输出的次数由标签的属性决定:
步骤一:编写标记处理类
package tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

/**
*
* doStartTag()中的返回值EVAL_BODY_INCLUDE,可以直接将标签的正文内容输出到浏览器中。
* doAfterBody()在处理完一次正文后会自动执行,
* 该方法如果返回EVAL_BODY_AGAIN,则代表再处理一遍正文(即输出到浏览器),返回SKIP_BODY 代表正文处理到此结束。
* 本例中循环向浏览器中输出标记体的正文,直到属性loop 的值小于1。
*
*/

public class TestBodyTag extends BodyTagSupport
{
private int loop ; //定义输出标签体的次数属性,比如:2的话就表示连续重复输出标签体2次

public void setLoop(int loop)
{
this.loop = loop;
}

public int doStartTag() throws JspException
{
if(loop>0){
return EVAL_BODY_INCLUDE; //自动将标签体包含到输出流中,第一次将标签体输出到浏览器中.
}else {
return SKIP_BODY; //跳过标签体,不将标签体包含到输出流,不处理标签体,直接忽略.
}
}

public int doAfterBody() throws JspException
{
/**
* doAfterBody()在处理完一次正文后会自动执行,
* 该方法如果返回EVAL_BODY_AGAIN,则代表再处理一遍正文(即输出到浏览器),返回SKIP_BODY 代表正文处理到此结束。
* 本例中循环向浏览器中输出标记体的正文,直到属性loop 的值小于1。
*/
if(loop>1){
loop--;
return EVAL_BODY_AGAIN;
}else {
return SKIP_BODY;
}
}
}

步骤二:创建标记库描述符文件testbodytag.tld,该文件要存放在 WEB-INF/test-tld 目录下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<!--
解释:
在tld 文件中,映射了标记名和处理程序类;
<tallib>元素,代表开始一个标记库的描述
<tligversion>元素,代表标记库的版本
<jspversion>元素,代表标记所支持的JSP 的版本
<shortname>为标记库起别名,相当于注释,无实际用途
<tag>元素,代表开始描述一个标记,其下子元素如下:
<name>——为标记处理类起的标记名
<tagclass>——指定标记处理类的全名(即带包的名字)
<bodycontent>——标记体的类型,该示例中不需要标记体,所有设置为EMPTY,该值的其他取值在后续内容中讲解
<tag>中的子元素
<attribute>用于为标签声明属性,其子元素如下:
<name>——用于指定属性名称
<required>——用于声明该属性是否为必需的,本例中声明color、loop 两个属性都不是必需的。
-->
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>test</shortname> <!-- 标签以<myhr:XXX
/>形式 -->
<tag>
<name>bodytag</name> <!-- 该标签为<myhr:MyHr
/> -->
<tagclass>tag.TestBodyTag</tagclass>
<bodycontent>tagdependent</bodycontent>
<attribute>
<name>loop</name>
<required>true</required>
</attribute>
</tag>
</taglib>

步骤三:在JSP 中使用该标记
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="test" uri="/WEB-INF/test-tld/testbodytag.tld" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>测试自定义带标签体的标签</title>
</head>
<body>
测试带标记体的自定义标记:<br>
<test:bodytag loop="4">
这是标记体<br />
</test:bodytag>
</body>
</html>

运行图:



5.3 一个简单的带标记体的标签(二)
在doStartTag()方法中返回EVAL_BODY_INCLUDE,简单地将标记体的内容直接输出到了浏览器中,并未对内容进行任何处理,在一些业务中有时需要对标记体正文进行处理,以下示例演示了如何读取标记体内容并进行处理:

步骤一:编写标记处理类
package tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

/*
* doStratTag()中的返回值EVAL_BODY_BUFFERED 代表不直接将标记体内容写到输出流中,
* 而是缓存到成员变量bodyContent 中(该成员从BodyTagSupport 继承过来),
* EVAL_BODY_INCLUDE是直接将标记体内容写到输出流中
* */

public class EqualTag extends BodyTagSupport{

private String name = "";
private String value = "";
public void setName(String
name) {
this.name = name;
}

public void setValue(String
value) {
this.value = value;
}

public int doStartTag() throws JspException
{
System.out.println("do starttag()....");
return EVAL_BODY_BUFFERED; //不直接将标记体内容写到输出流中,而是缓存到成员变量bodyContent 中
}

public void setBodyContent(BodyContent
b) {
System.out.println("setBodycontent()...."+b.getString()+"++");
this.bodyContent =
b; //bodyContent 赋值前,bodyContent是空的
System.out.println("setBodycontent()...."+bodyContent.getString()+"++");
}

//初始化标记体
public void doInitBody() throws JspException
{
System.out.println("doInitBody()....."+bodyContent.getString()+"++");
}

public int doAfterBody() throws JspException
{
System.out.println("doAfterBody()...."+bodyContent.getString()+"++");
return SKIP_BODY; //停止包含
}

public int doEndTag() throws JspException
{ //处理标签体内容,将标签体的内容加租倾斜
System.out.println("doEndTag()..."+bodyContent.getString()+"++");
String username = (String)pageContext.getSession().getAttribute(name); //获得存在session的某属性的值,该属性值由标签属性提供获取。
String str = bodyContent.getString();

if(username.equals(value)){ //如果该值与标签属性相等
str = "<b><i>"+str+"</i></b>"; //加粗倾斜,不是的话就原样输出
}

try {
JspWriter out = pageContext.getOut();
out.print(str); //将加粗倾斜后的标签体输出到页面上
this.bodyContent = null;
} catch (Exception e) {
e.printStackTrace();
}

return EVAL_PAGE;
}
}

步骤二:在标记库描述符文件testbodytag.tld,添加tag标记:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<!--
解释:
在tld 文件中,映射了标记名和处理程序类;
<tallib>元素,代表开始一个标记库的描述
<tligversion>元素,代表标记库的版本
<jspversion>元素,代表标记所支持的JSP 的版本
<shortname>为标记库起别名,相当于注释,无实际用途
<tag>元素,代表开始描述一个标记,其下子元素如下:
<name>——为标记处理类起的标记名
<tagclass>——指定标记处理类的全名(即带包的名字)
<bodycontent>——标记体的类型,该示例中不需要标记体,所有设置为EMPTY,该值的其他取值在后续内容中讲解
<tag>中的子元素
<attribute>用于为标签声明属性,其子元素如下:
<name>——用于指定属性名称
<required>——用于声明该属性是否为必需的,本例中声明color、loop 两个属性都不是必需的。
-->
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>test</shortname> <!-- 标签以<myhr:XXX
/>形式 -->
<tag>
<name>bodytag</name> <!-- 该标签为<myhr:MyHr
/> -->
<tagclass>tag.TestBodyTag</tagclass>
<bodycontent>tagdependent</bodycontent>
<attribute>
<name>loop</name>
<required>true</required>
</attribute>
</tag>
<tag>
<name>equal</name>
<tagclass>tag.EqualTag</tagclass>
<bodycontent>tagdependent</bodycontent>
<attribute>
<name>name</name>
<required>true</required>
</attribute>
<attribute>
<name>value</name>
<required>true</required>
</attribute>
</tag>
</taglib>

步骤三:在JSP 中使用该标记
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="test" uri="/WEB-INF/test-tld/testbodytag.tld" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>测试自定义带标签体的标签</title>
</head>
<body>
<% session.setAttribute("username","tom"); %>
<test:equal name="username" value="tom">session中的username的属性值如果是tom,则这段文字加粗倾斜</test:equal>
<br />
<test:equal name="username" value="tom1">session中的username的属性值如果是tom,则这段文字加粗倾斜</test:equal>
</body>
</html>

运行界面如下:



后台输出如下:
do starttag()....
setBodycontent()....++
setBodycontent()....++
doInitBody().....++
doAfterBody()....session中的username的属性值如果是tom,则这段文字加粗倾斜++
doEndTag()...session中的username的属性值如果是tom,则这段文字加粗倾斜++
do starttag()....
setBodycontent()....++
setBodycontent()....++
doInitBody().....++
doAfterBody()....session中的username的属性值如果是tom,则这段文字加粗倾斜++
doEndTag()...session中的username的属性值如果是tom,则这段文字加粗倾斜++

另外,附上各标签的方法的返回值综述:



六、标签中的子标记
一个标签中可以再包含其他的子标记,这种标签称为嵌套标记。创建嵌套标签时,标记处理类与普通标签相似,但在doStartTag()方法中必须返回EVAL_BODY_INCLUDE,JSP 容器才会处理嵌套的子标记。

步骤一:编写顶级标记处理类
package tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class NestTag extends BodyTagSupport{
private String name = "";
private String value = "";
public void setName(String name)
{
this.name = name;
}

public void setValue(String value)
{
this.value = value;
}

public int doStartTag() throws JspException
{
String username = (String)pageContext.getSession().getAttribute(name);
if(username.equals(value)){
return EVAL_BODY_INCLUDE; //自动将标签体包含到输出流(因为顶级标签的标签体是一子标签,还要进行该子标签的标签处理)
}else{
return SKIP_BODY; //跳过标签体,不处理
}
}

}

步骤二:在标记库描述符文件testbodytag.tld,添加tag标记:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<!--
解释:
在tld 文件中,映射了标记名和处理程序类;
<tallib>元素,代表开始一个标记库的描述
<tligversion>元素,代表标记库的版本
<jspversion>元素,代表标记所支持的JSP 的版本
<shortname>为标记库起别名,相当于注释,无实际用途
<tag>元素,代表开始描述一个标记,其下子元素如下:
<name>——为标记处理类起的标记名
<tagclass>——指定标记处理类的全名(即带包的名字)
<bodycontent>——标记体的类型,该示例中不需要标记体,所有设置为EMPTY,该值的其他取值在后续内容中讲解
<tag>中的子元素
<attribute>用于为标签声明属性,其子元素如下:
<name>——用于指定属性名称
<required>——用于声明该属性是否为必需的,本例中声明color、loop 两个属性都不是必需的。
-->
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>test</shortname> <!-- 标签以<myhr:XXX
/>形式 -->
<tag>
<name>bodytag</name> <!-- 该标签为<myhr:MyHr
/> -->
<tagclass>tag.TestBodyTag</tagclass>
<bodycontent>tagdependent</bodycontent>
<attribute>
<name>loop</name>
<required>true</required>
</attribute>
</tag>
<tag>
<name>equal</name>
<tagclass>tag.EqualTag</tagclass>
<bodycontent>tagdependent</bodycontent>
<attribute>
<name>name</name>
<required>true</required>
</attribute>
<attribute>
<name>value</name>
<required>true</required>
</attribute>
</tag>
<tag>
<name>nest</name>
<tagclass>tag.NestTag</tagclass>
<bodycontent>JSP</bodycontent> <!-- 该声明标记体是其他标记,也可以是Jsp标准标记 -->
<attribute>
<name>name</name>
<required>true</required>
</attribute>
<attribute>
<name>value</name>
<required>true</required>
</attribute>
</tag>
</taglib>

步骤三:在JSP 中使用该标记
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="test" uri="/WEB-INF/test-tld/testbodytag.tld" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>测试嵌套的标签</title>
</head>
<body>
<% session.setAttribute("username","tom"); %>

<test:nest name="username" value="tom">
<test:bodytag loop="3">
session中的用户名是tom<br/>
</test:bodytag>
</test:nest>
</body>
</html>

运行界面如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: