回到顶部


<%@ 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>
posted on 2018-04-17 16:00  ssgao  阅读(170)  评论(0编辑  收藏  举报