自定义标签

1、概述html

 

JSP 2.0 中提供了两种新的开发自定义标记的方法:java

一、简单标签机制SimpleTagweb

JSP 2.0 中加入了新的建立自定义标记的API:javax.servlet.jsp.tagext.SimpleTag,该API 定义了用来实现简单标记的接口。和JSP 1.2 中的已有接口不一样的是,SimpleTag 接口不使用doStartTag()和doEndTag()方法,而提供了一个简单的doTag()方法。这个方法在调用该标记时只被使用一次。一个自定义标记中实现的全部逻辑都在这个方法中实现。相对JSP1.2 中自定义标记机制,SimpleTag 的方法和处理周期要简单得多。后端

 

二、 标签文件浏览器

标签文件容许JSP 网页做者使用JSP 语法建立可复用的标签库。标签文件的扩展名必须是.tag。缓存

 

1.1 使用简单标签机制网络

与JSP1.2 类似,开发自定义标签要遵循“开发标记类---配置TLD 文件----在JSP 中使用”的过程,session

示例以下:app

步骤一:编写标记处理类AddTag.javajsp

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标签分为标准JSP 环境自带的标签(即前面章节中学习过的JSP 动做标签)和JSP 自定义标签。JSP 自定义标签是用户定义的标记,它遵循XML 语法。当servlet 容器处理自定义标记时,会自动调用一个Java 类文件完成相对应的功能。

Java 开发人员编写标记处理程序类以处理标记并处理全部须要的Java 代码和数据操做。对于Web页面设计者来讲,自定义标记与标准HTML 标记使用起来没什么区别,但HTML 标记只能完成前台显示的功能,而自定义标记能够在后台完成某些操做。

正确编写自定义标记可让 Web 设计者建立、查询和操做数据而无需编写一行Java 代码。正确使用自定义标记使 Java 开发人员没必要再在编码过程当中考虑表示层。这样应用程序开发小组的每一位成员均可以关注于他或者她最擅长的事物。

因此说,JSP 自定义标记为在动态Web 页中将表示与业务逻辑分离提供了一种标准化的机制,使页面设计者能够将注意力放到表示上,而应用程序开发人员编写后端的代码。

 

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,用于建立带标记体的标签。

    一般咱们自定义的标签,编写处理程序时使用TagSupport 和BodyTagSupport 便可,不须要涉及到标签体的,继承TagSupport,须要用标签体的,用BodyTagSupport,如下是开发和使用一个JSP 自定义标签的全过程:

1) 开发标记处理类,编译生成class 文件,该类要继承TagSupport 或BodyTagSupport;

2) 建立标记库描述符文件*.tld,在该文件中为标记处理类指定标签名、声明标签属性;

3) 在JSP 中引用标签库;

4) 在JSP 中使用标JSP 标签

 

3、自结束标签(不带标签体,TagSupport)

3.1 自结束标签简介

这是一种不带标记体的标签,因此该类标签的处理类直接继承javax.servlet.jsp.tagext.TagSupport便可。TagSupport 的主要方法以下:

public int doStartTag() throws JspException

在WEB 容器遇到标签开始时,该方法会运行。

public int doEndTag() throws JspException

在WEB 容器遇到标签结束时,该方法会运行。

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

 

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()方法;

 *2doStartTag()方法的返回值:一般能够取两个值:

 *      EVAL_BODY_INCLUDE——包含标记体,本例中要编写自结束标记因此不使用该值;

 *      SKIP_BODY——跳过标记体,即不处理标记体,开发自结束标记应该使用该值。

 *3doEndTag()方法的返回值:一般能够取两个值:

 *      SKIP_PAGE——返回这个值,则终止页面执行;

 *      EVAL_PAGE——返回该值则处理完当前标记后,JSP页面停止运行。

 */

 

publicclass MyHrTag extends TagSupport{

 

    /**

     *

     */

    privatestaticfinallongserialVersionUID = 1L;

 

    /*

     * WEB 容器遇到标签开始时,该方法会运行。

     * 该方法能够自行定义,也能够不定义。不定义该方法则遇到开始标签什么都不作

     * */

    publicint doStartTag() throws JspException {

       try {

           //获得网络输出流,pageContext 是从父类继承过来的成员

           JspWriter out = pageContext.getOut();

           //向网页输出内容

           out.println("<h4>开始执行doStartTag()......</h4>");

           //输出条水平线;

           for(int i=1; i<=5; i++){

              out.println("<hr>");

           }

       catch (Exception e) {

           e.printStackTrace();

       }

       //return EVAL_BODY_INCLUDE; //处理标记体

       return Tag.SKIP_BODY//跳过标记体;

    }

   

    /*

     * WEB 容器遇到标签结束时,该方法会运行。

     * 该方法能够自行定义,也能够不定义。不定义该方法则遇到结束标签什么都不作

     * */

    publicint doEndTag() throws JspException {

       try {

           JspWriter out=pageContext.getOut();

           out.println("<h3>开始执行doEndTag().....</h3>.");

       catch (Exception e) {

           e.printStackTrace();

       }

       //return Tag.SKIP_PAGE; //返回这个值,则终止页面执行;

       returnEVAL_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、标签中的属性

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类型,

 *但要求提供publicgetset方法。

 * 

 */

 

publicclass MyHrTag2 extends TagSupport{

   

    //声明属性

    private String color = "black"//定义线条颜色

    private String loop = "1"//定义输出水平线的条数

   

    //严格按照javabean模式

    publicvoid setColor(String color) {

       this.color = color;

    }

   

    //严格按照javabean模式

    publicvoid setLoop(String loop) {

       this.loop = loop;

    }

   

    //只定义遇到开始标签执行方法便可了。

    publicint 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>——用于声明该属性是否为必需的,本例中声明colorloop 两个属性都不是必需的。

 -->

<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;

 

publicclass LoginTag extends TagSupport{

 

    publicint doStartTag() throws JspException {

       try {

           HttpSession session = pageContext.getSession();

           Object obj = session.getAttribute("User");

           //判断是否从未登陆过,若是没登陆过则转到登陆页;

           if(obj==null){

              ((HttpServletResponse)pageContext.getResponse()).sendRedirect("login.html");

              returnSKIP_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>——用于声明该属性是否为必需的,本例中声明colorloop 两个属性都不是必需的。

 -->

<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、标签中的标记体

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 的处理流程以下:

         一、当容器建立一个新的标签实例后,经过setPageContext 来设置标签的页面上下文。

二、使用setParent 方法设置这个标签的上一级标签,若是没有上一级嵌套,设置为null。

三、设置标签的属性,若是没有定义属性,就不调用此类方法。

四、调用doStartTag 方法,这个方法能够返回如下三者之一:EVAL_BODY_INCLUDE、

EVAL_BODY_BUFFERED、SKIP_BODY,当返回EVAL_BODY_INCLUDE 时,就将标记

体直接写到输出流中,若是返回SKIP_BODY,就再也不计算标签的正文,若是返回EVAL_BODY_BUFFERED,就将标记体的正文包含到bodyContent 成员中。

五、调用setBodyContent 设置当前的BodyContent.

六、调用doInitBody,能够在该方法中对BodyContent 进行一些初始化操做.每次计算完Body 后调用doAfterBody,若是返回EVAL_BODY_AGAIN,表示继续处理一次标记体,直到返回SKIP_BODY 才继续往下执行.

七、调用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

 *

 */

 

publicclass TestBodyTag extends BodyTagSupport {

    privateintloop ; //定义输出标签体的次数属性,好比:2的话就表示连续重复输出标签体2

 

    publicvoid setLoop(int loop) {

       this.loop = loop;

    }

 

    publicint doStartTag() throws JspException {

       if(loop>0){

           returnEVAL_BODY_INCLUDE//自动将标签体包含到输出流中,第一次将标签体输出到浏览器中.

       }else {

           returnSKIP_BODY//跳过标签体,不将标签体包含到输出流,不处理标签体,直接忽略.

       }

    }

 

    publicint doAfterBody() throws JspException {

       /**

        *doAfterBody()在处理完一次正文后会自动执行,

        *该方法若是返回EVAL_BODY_AGAIN,则表明再处理一遍正文(即输出到浏览器),返回SKIP_BODY表明正文处理到此结束。

        *本例中循环向浏览器中输出标记体的正文,直到属性loop的值小于1

        */

       if(loop>1){

           loop--;

           returnEVAL_BODY_AGAIN;

       }else {

           returnSKIP_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>——用于声明该属性是否为必需的,本例中声明colorloop 两个属性都不是必需的。

 -->

<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是直接将标记体内容写到输出流中

 * */

 

publicclass EqualTag extends BodyTagSupport{

 

    private String name = "";

    private String value = "";

    publicvoid setName(String name) {

       this.name = name;

    }

 

    publicvoid setValue(String value) {

       this.value = value;

    }

 

    publicint doStartTag() throws JspException {

       System.out.println("do starttag()....");

       returnEVAL_BODY_BUFFERED;  //不直接将标记体内容写到输出流中,而是缓存到成员变量bodyContent 

    }  

 

    publicvoid setBodyContent(BodyContent b) {

       System.out.println("setBodycontent()...."+b.getString()+"++");

       this.bodyContent = b;  //bodyContent 赋值前,bodyContent是空的

       System.out.println("setBodycontent()...."+bodyContent.getString()+"++");

    }

 

    //初始化标记体

    publicvoid doInitBody() throws JspException {

       System.out.println("doInitBody()....."+bodyContent.getString()+"++");

    }

   

    publicint doAfterBody() throws JspException {

       System.out.println("doAfterBody()...."+bodyContent.getString()+"++");

       returnSKIP_BODY;  //中止包含

    }

 

    publicint 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();

       }

   

       returnEVAL_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>——用于声明该属性是否为必需的,本例中声明colorloop 两个属性都不是必需的。

 -->

<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,则这段文字加粗倾斜++

 

 

 

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

 

 

 

 

6、标签中的子标记

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

 

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

package tag;

 

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.tagext.BodyTagSupport;

 

publicclass NestTag extends BodyTagSupport{

    private String name = "";

    private String value = "";

    publicvoid setName(String name) {

       this.name = name;

    }

 

    publicvoid setValue(String value) {

       this.value = value;

    }

 

    publicint doStartTag() throws JspException {

       String username = (String)pageContext.getSession().getAttribute(name);

       if(username.equals(value)){

           returnEVAL_BODY_INCLUDE//自动将标签体包含到输出流(由于顶级标签的标签体是一子标签,还要进行该子标签的标签处理)

       }else{

           returnSKIP_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>——用于声明该属性是否为必需的,本例中声明colorloop 两个属性都不是必需的。

 -->

<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>

 

运行界面以下:

 

 

 

 

相关文章
相关标签/搜索