<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 引入标签库: prefix是必须含有的不可缺少 -->
<%@ taglib uri="/ssgao" prefix="ssgao" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
输出标签信息
<!-- 在JSp页面中使用自定义标签gs,gs标签是带有标签体的,其标签体的内容是:我的宝贝是笑笑 -->
<ssgao:aouo>
我的宝贝是笑笑
</ssgao:aouo>
</body>
</html>
JspTag接口*
该接口是所有自定义标签的父接口,是jsp2.0中新定义的标记接口,没有任何属性和方法。JspTag的接口有Tag和SimpleTag两个直接子接口,jsp2.0之前的版本只有Tag接口,所以实现Tag接口的自定义标签页叫做传统标签把实现SimpleTag接口的自定义标签叫做简单标签
Tag接口
Tag接口是所有传统标签的父接口,其中定义了两个重要的方法(doStartTag,doEndTag)方法和四个常量(EVAL_BODY_INCLUDE,SKIP_BODY,EVAL_PAGE.SKIP_PAGE)这两个方法和四个常量的作用如下:
从WEB容器在解释执行JSP页面的过程中,遇到自定义的标签的开始标记就会去调用标签处理器的doStartTag方法,doStartTag方法执行完后可以向WEB容器返回常量EVAL_BODY_INCLUDE或SKIP_BODY。如果doStartTag方法返回EVAL_BODY_INCLUDE,WEB容器就会接着执行自定义标签的标签体。如果doStartTag方法返回SKIP_BODY,WEB容器就会忽略自定义标签的标签体,直接解释执行自定义标签的结束标记。
WEB容器解释执行到自定义标签的结束标记时,就会调用标签处理器的doEndTag方法,doEndTag方法执行完后可以向WEB容器返回常量EVAL_PAGE或KIP_PAGE。如果doEndTag方法返回常量EVAL_PAGE,WEB容器就会接着执行JSP页面中位于结束标记后面的JSP代码;如果doEndTag方法返回SKIP_TAG,WEB容器就会忽略JSP页面中位于标记后面的所有内容。
从doStartTag和doEndTag方法的作用和返回值的作用可以看出,开发自定义的标签时,可以在doStartTag方法和doEndTag方法体内编写适合Java程序代码来实现具体的功能。通过控制doStartTag方法和doEndTag方法的返回值,还可以告诉WEB容器是否执行自定义标签中的标签体内容和JSP页面中位于自定义标签结束标记后面的内容。
Iteration Tag接口
IterationTag接口继承了Tag接口,并在Tag接口的基础上增加一个doAfterBody的方法和一个EVAL_BODY_AGAIN常量。实现IterationTag接口的标签除了可以完成Tag接口所能完成功能外,还能够通知WEB容器是否重复执行标签体内容。对于实现了ITerationTag接口的自定义标签,WEB容器在执行完自定义标签的标签体后,将调用标签处理器的doAfterBody方法,doAfterBody方法可以向WEB容器返回常量EVAL_BODY_AGAIN或SKIP_BODY。如果doAfterBody方法返回EVAL_BODY_AGAIN,WEB容器就会把标签体内容重复执行一次,执行完后接着在调用doAfterBody方法,如此往复,直到doAfterBody方法返回常量SKIP_BODY.WEB容器才会开始处理标签的结束标记和调用doEndTag方法。
可见,开发自定义标签时,可以通过控制doAfterBody方法的返回值来告诉WEB容器是否重复执行标签体内容,从而达到循环处理标签体内容的效果。例如,可以通过一个实现IterationTag接口的标签来迭代输出一个集合中所有元素,在标签体部分指定元素的输出格式。
BodyTag接口
BodyTag接口继承了IterationTag接口,并在IterationTag接口的基础上增加了两个方法(setBodyContent、doInitBody)和一个EVAL_BODY_BUFFERED常量。实现BodyTag接口的标签除了可以完成IterationTag接口所能完成的功能,还可以对标签体内容进行修改。对于实现了BodyTag接口的自定义标签,标签处理器的doStartTag方法不仅可以返回前面讲解的常量EVAL_BODY_INCLUDE或SKIP_BODY,还可以返回常量EVAL_BODY_BUFFERED。如果doStartTag方法返回EVAL_BODY_BUFFERED,WEB容器就会创建一个专用于捕获标签体运行结果的BodyContent对象,然后调用标签处理器的setBodyContent方法将BodyContent对象的引用传递给标签处理器,WEB容器接着将标签体的执行结果写入到BodyContent对象中。在标签处理器的后续事件方法中,可以通过先前保存的BodyContent对象的引用来获取标签体的执行结果,然后调用BodyContent对象特有的方法对BodyContent对象中的内容(即标签体的执行结果)进行修改和控制其输出。
在JSP API中也提供了BodyTag接口的实现类BodyTagSupport,我们在编写能够修改标签体内容的自定义标签的标签处理器类时,可以继承和扩展BodyTagSupport类,这相比实现BodyTag接口将简化开发工作
SimpleTag 接口
SimpleTag接口是JSP2.0中新增的一个标签接口。由于传统标签使用三个标签接口来完成不同的功能,显得过于繁琐,不利于标签技术的推广,因此,SUN公司为降低标签技术的学习难度,在JSP 2.0中定义了一个更为简单、便于编写和调用的SimpleTag接口。SimpleTag接口与传统标签接口最大的区别在于,SimpleTag接口只定义了一个用于处理标签逻辑的doTag方法,该方法在WEB容器执行自定义标签时调用,并且只被调用一次。那些使用传统标签接口所完成的功能,例如是否执行标签体、迭代标签体、对标签体内容进行修改等功能都可以在doTag方法中完成。
在JSP API中也提供了SimpleTag接口的实现类SimpleTagSupport,我们在编写简单标签时,可以继承和扩展SimpleTagSupport类,这相比实现SimpleTag接口将简化开发工作
传统标签接口中的各个方法可以返回返回值得说明
返回值和方法名 | EVAL_BODY_INCLUDE | SKIP_BODY | EVAL_BODY_BUFFEREDY | EVAL_BODY_AGAIN | EVAL_PAGE | SKIP_PAGE |
---|---|---|---|---|---|---|
doStartTag | 将标签体的执行结果插入到输出流中 | 忽略标签体部分 | 将标签提的执行接口放入到一个BodyContent对象中 | X | X | X |
doAfterBody | X | 不在重复执行标签体内容 | X | 重复执行标签内容 | X | X |
doEndTag | X | X | X | X | 继续处理结果标签后面的所有JSP代码 | 忽略结束标签后面的所有JSP代码 |
传统标签实现页面逻辑
控制jsp页面某一部分内容是否执行
控制整个jsp页面是否执行
控制jsp页面内容重复执行
修改jsp页面内容输出
控制jsp页面的自定义标签体是否执行
编写一个类实现tag接口,控制doStartTag()方法的返回值,如果整个方法返回EVAL_BODY_INCLUDE,则执行标签体,如果返回SKIP_BODY则不执行
SUN公司针对tag接口提供了一个默认的实现类TagSupport,TagSupport类中实现了tag接口的所有方法,因此我们可以编写一个类集成TagSupport,然后在重写doStartTag方法
package demo.tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
/**
* TagSupport类实现了Tag接口,TagtwoDemo继承了TagSupport
* @author ssgao
*
*/
public class TagtwoDemo extends TagSupport{
/** */
private static final long serialVersionUID = 7332955146947736164L;
/**
* 重写doStartTag方法,来控制标签提是否执行
*/
@Override
public int doStartTag() throws JspException {
JspWriter jw =pageContext.getOut();
try {
jw.write("自定义标签->");
} catch (IOException e) {
e.printStackTrace();
}
/**
* 如果返回EVAL_BODY_INCLDE,则执行标签体
* 如果返回SKIP_BODY 则不执行标签体
*/
return Tag.EVAL_BODY_INCLUDE;
}
}
在WEB-INF目录下tld文件中添加对该标签处理的描述
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd" >
<taglib>
<tlib-version>tlib-version</tlib-version>
<jsp-version>jsp-version</jsp-version>
<short-name>short-name</short-name>
<uri>/ssgao</uri>
<tag>
<name>aouo</name>
<tag-class>demo.tag.TagtwoDemo</tag-class>
<body-content>JSP</body-content>
</tag>
</taglib>
在JSP页面中引入标签库
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 引入标签库: prefix是必须含有的不可缺少 -->
<%@ taglib uri="/ssgao" prefix="ssgao" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
输出标签信息
<!-- 在JSp页面中使用自定义标签gs,gs标签是带有标签体的,其标签体的内容是:我的宝贝是笑笑 -->
<ssgao:aouo>
我的宝贝是笑笑
</ssgao:aouo>
</body>
</html>
控制整个JSP页面是否执行
编写一个类实现Tag接口,控制doEndTag方法的返回值,如果这个方法返回EVAL_PAGE,则执行标签下的JSP页面,如果返回SKIP_PAGE则不执行余下的JSP
package demo.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
/**
* TagSupport类实现了Tag接口,TagtwoDemo继承了TagSupport
* @author ssgao
*
*/
public class EndTagDemo extends TagSupport{
/** */
private static final long serialVersionUID = 7332955146947736164L;
/**
* 重写doEndTag方法控制JSP页面是否执行
*/
public int doEndTag() throws JspException {
/**
* 如果返回EVAL_PAGE,则执行标签余下的JSP页面
* 如果返回SKIP_PAGE,则不执行余下的JSP页面
*/
return Tag.SKIP_PAGE;
}
}
在WEB-INF目录下tld文件中添加对该标签处理的描述
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd" >
<taglib>
<tlib-version>tlib-version</tlib-version>
<jsp-version>jsp-version</jsp-version>
<short-name>short-name</short-name>
<uri>/end</uri>
<tag>
<name>end</name>
<tag-class>demo.tag.EndTagDemo</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
在JSP页面中引入标签库
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 引入标签库: prefix是必须含有的不可缺少 -->
<%@ taglib uri="/end" prefix="gs" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 在JSp页面中使用自定义标签gs,gs标签是带有标签体的,其标签体的内容是:我的宝贝是笑笑 -->
<gs:end/>
输出标签信息
</body>
</html>
JSP页面内容重复执行
编写一个类实现Iterationtag接口控制doAfterBody()方法的返回值,如果这个方法返回EVAL_BODY_AGAIN,则web服务器重复执行一次标签体,一次类推,知道doAfterBody方法返回SKIP_BODY
则标签体才不会重复执行
package demo.tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.IterationTag;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
/**
* TagSupport类实现了Tag接口,TagtwoDemo继承了TagSupport
* @author ssgao
*
*/
public class AfterTagDemo extends TagSupport{
/** */
private static final long serialVersionUID = 7332955146947736164L;
static int no;
static{
no=5;
}
/**
* 重写doStartTag方法,来控制标签提是否执行
*/
@Override
public int doStartTag() throws JspException {
/**
* 如果返回EVAL_BODY_INCLDE,则执行标签体
* 如果返回SKIP_BODY 则不执行标签体
*/
return Tag.EVAL_BODY_INCLUDE;
}
@Override
public int doAfterBody() throws JspException {
no--;
while(no>0){
return IterationTag.EVAL_BODY_AGAIN;
}
return IterationTag.SKIP_BODY;
}
}
在WEB-INF目录下tld文件中添加对该标签处理的描述
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd" >
<taglib>
<tlib-version>tlib-version</tlib-version>
<jsp-version>jsp-version</jsp-version>
<short-name>short-name</short-name>
<uri>/after</uri>
<tag>
<name>after</name>
<tag-class>demo.tag.AfterTagDemo</tag-class>
<body-content>JSP</body-content>
</tag>
</taglib>
在JSP页面中引入标签库
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 引入标签库: prefix是必须含有的不可缺少 -->
<%@ taglib uri="/after" prefix="ssgao" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
输出标签信息
<!-- 在JSp页面中使用自定义标签gs,gs标签是带有标签体的,其标签体的内容是:我的宝贝是笑笑 -->
<ssgao:after>
我的宝贝是笑笑
</ssgao:after>
</body>
</html>
修改JSP页面内容输出
编写一个类实现BodyTag接口,控制doStartTag方法返回EVAL_BODY_BUFFERED,则WEB服务器会创建BodyContent对象捕获标签体,然后在doEndTag()方法体内,得到代表标签体的bodyContent对象
从而就可以对标签体进行修改操作
sun公司针对BodyTag接口提供一个默认的实现类BodyTagSupport,BodyTagSupport类中实现了BodyTag接口的所有方法,因此我们可以编写一个类继承BodyTagSupport类,然后在根据需要重写doStartTag方法和doEndTag方法。
package demo.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTag;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.Tag;
/**
* BodyTagSupport类实现了BodyTag接口接口,EditTagDemo继承 BodyTagSupport类
* @author ssgao
*
*/
public class EditTagDemo extends BodyTagSupport{
/** */
private static final long serialVersionUID = -3814095430415404149L;
/**
* 控制doStartTag()方法返回EVAL_BODY_BUFFERED
*/
@Override
public int doStartTag() throws JspException {
return BodyTag.EVAL_BODY_BUFFERED;
}
@Override
public int doEndTag() throws JspException {
/**this.getBodyContent()得到代表标签体的bodyContent对象 */
BodyContent bodyContent=this.getBodyContent();
//拿到标签体
String content = bodyContent.getString();
//修改标签体里面的内容,将小写转换为大写
String result = content.toUpperCase();
try {
/** 输出修改后的内容*/
this.pageContext.getOut().write(result);
} catch (Exception e) {
e.printStackTrace();
}
return Tag.EVAL_PAGE;
}
}
在WEB-INF目录下tld文件中添加对该标签处理的描述
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd" >
<taglib>
<tlib-version>tlib-version</tlib-version>
<jsp-version>jsp-version</jsp-version>
<short-name>short-name</short-name>
<uri>/edit</uri>
<tag>
<name>edit</name>
<tag-class>demo.tag.EditTagDemo</tag-class>
<body-content>JSP</body-content>
</tag>
</taglib>
在JSP页面中引入标签库
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 引入标签库: prefix是必须含有的不可缺少 -->
<%@ taglib uri="/edit" prefix="ssgao" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
输出标签信息
<ssgao:edit>
sadasd
</ssgao:edit>
</body>
</html>