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

JSP:自定义标签——开发实例

2014-04-02 11:40 357 查看
开发带属性的标签:helloTagHaveProp

  本实例中开发的标签在实例108的helloTag标签上作出改进,开发目标是在helloTag标签上增加两个属性fontSize和fontColor,fontSize用于设置字体大小,fontColor用于设置文字的颜色。

  (1)第一步:开发标签实现类。

  
helloTagHaveProp.java

  package hello;

  import javax.servlet.jsp.JspWriter;

  import javax.servlet.jsp.tagext.TagSupport;

  public class helloTagHaveProp extends TagSupport {

    private String fontSize="3";//字体大小,默认3号

    private String fontColor="#000000";//字体颜色,默认黑色

    //----标签开始时调用此方法-------

    public int doStartTag(){

        try{

            JspWriter out=pageContext.getOut();

            out.print("标签开始了。<font color=\""+fontColor +

                 "\" size=\""+fontSize+"\">hello!</font>");

        }catch(Exception e){

            System.out.println(e);

        }

        return EVAL_BODY_INCLUDE;

    }

    //----标签结束时调用此方法-------

    public int doEndTag(){

        try{

            JspWriter out=pageContext.getOut();

            out.print("标签结束了。");

        }catch(Exception e){

            System.out.println(e);

        }

        return EVAL_PAGE;

    }   

    public String getFontColor() {  

        return fontColor;

    }

    public void setFontColor(String fontColor) {

        this.fontColor = fontColor;

    }

    public String getFontSize() {

        return fontSize;

    }

    public void setFontSize(String fontSize) {

        this.fontSize = fontSize;

      }

  }
  (2)第二步:编写标签描述tld文件。这里在myTag.tld文件中增加内容,在<taglib>与</taglib>之间增加的内容如下:

  
<!-- helloTagHaveProp-->

  <tag>

     <!-- 标签名称-->

     <name>helloTagHaveProp</name>

     <!-- 标签对应的处理类-->

     <tag-class>hello.helloTagHaveProp</tag-class>

     <!-- 标签体内容,没有标签体则设为empty-->

     <body-content>empty</body-content>

     <!-- 标签的属性声明-->

     <attribute>

      <name>fontSize</name>

      <required>false</required>

     </attribute>

     <attribute>

      <name>fontColor</name>

      <required>false</required>

     </attribute>

  </tag>
  其中,name为属性的名称,required设置此属性是否必须设置,如果为true则在JSP页面中使用此标签时,必须给标签的这个属性赋值。

  (3)第三步:在Web应用的web.xml文件中声明标签库引用。本例与实例108使用同一个tld文件,故不必再修改。

  (4)第四步:在JSP页面中声明并调用标签。

  
useHelloTagHaveProp.jsp

  <%@ taglib uri="/myTag" prefix="myTag" %>

  <%@ page contentType="text/html;charset=GB2312" %>

  <html>

    <head>

    <title>一个简单的自定义标签</title>

    </head> 

    <body>

   下面是应用这个简单的自定义标签的结果:<br>

  <myTag:helloTagHaveProp fontSize="5"/><br>

  <myTag:helloTagHaveProp fontSize="4" fontColor="red"/>

    </body>

  </html>
  程序的运行结果如图13-3所示。

  


  三、 开发带标签体的标签

  要开发带标签体的标签,可实现BodyTag接口,也可从BodyTag接口的实现类BodyTagSupport继承,为简化开发,推荐从BodyTagSupport类继承开发。

  编写标签对应的实现类时,需要重载BodyTagSupport类几个方法:doStartTag(), setBodyContent(), doInitBody(), doAfterBody(), doEndTag(),他们执行顺序如下:doStartTag()→doInitBody()→setBodyContent()→doAfterBody()→doEndTag()doStartTag()方法可返回EVAL_BODY_INCLUDE或SKIP_BODY,如果返回EVAL_BODY_ INCLUDE则继续执行;如果返回SKIP_BODY则接下来的doInitBody(),setBodyContent(),
doAfterBody()三个方法不会被执行,而直接执行doEndTag()方法。

  setBodyContent()方法用于设置标签体内容,如果在此之前要作一些初始化工作,则在doInitBody()方法中完成。标签体内容执行完后,会调用doAfterBody()方法,此方法可返回EVAL_BODY_TAG, SKIP_BODY,

  EVAL_PAGE或SKIP_PAGE.如果返回EVAL_BODY_TAG则会再次设置标签体内容,直到返回SKIP_BODY;如果返回EVAL_PAGE则标签体执行完后会继续执行JSP页面中接下来的部分;如果返回SKIP_PAGE,则JSP页面的后续内容将不再执行。

  开发带标签体的标签:bodyTag1

  本实例将要开发一个带标签体的标签bodyTag1,这个标签有一个属性countNum,用于设置输出标签体内容的次数,输出内容为当前的系统时间。

  (1)第一步:开发标签实现类。

  
  BodyTag1.java

  package body;

  import javax.servlet.jsp.JspWriter;

  import javax.servlet.jsp.tagext.BodyTagSupport;

  public class bodyTag1 extends BodyTagSupport{

    private int countNum=0;//循环显示时间的次数

    private int currentNum=1;//当前执行次数

    //----标签开始时调用此方法-------

    public int doStartTag(){

        try{

            JspWriter out=pageContext.getOut();

            out.print("标签开始了:<br>");

            if(countNum>0)

                return EVAL_BODY_TAG;

            else

                return SKIP_BODY;

  }catch(Exception e){

            System.out.println(e);

            return SKIP_BODY;

        }

    }

    //----标签体执行完后调用此方法----

    public int doAfterBody(){

        try{

         JspWriter out=pageContext.getOut();

         out.print("第"+currentNum+"次执行标签体。标签体执行完毕。<br>");

         if(countNum>1){//如果还需要执行标签体

             countNum--;

             currentNum++;

             return EVAL_BODY_TAG;

         }else return SKIP_BODY;

        }catch(Exception e){

            System.out.println(e);

            return SKIP_BODY;

        }

    }

    //----标签结束时调用此方法-------

    public int doEndTag(){

        try{

            JspWriter out=pageContext.getOut();

            //----输出标签体的内容----

            bodyContent.writeOut(bodyContent.getEnclosingWriter());

            out.print("标签结束了。");

        }catch(Exception e){

            System.out.println(e);

        }

        return EVAL_PAGE;

    }

    public int getCountNum() {

        return countNum;

    }

    public void setCountNum(int countNum) {

        untNum = countNum;

        this.currentNum=1;

      }

  }

  执行标签体并不会直接输出标签体中的内容,因此本实例在doEndTag()方法中一次性把执行的结果输出。

  (2)第二步:编写标签描述tld文件。

  因为本章所有实例共用一个Web应用,故本例在myTag.tld文件中增加内容。在<taglib>与</taglib>之间增加的内容如下:

  
<!-- bodyTag1-->

  <tag>

  <!-- 标签名称-->

  <name>bodyTag1</name>

  <!-- 标签对应的处理类-->

  <tag-class>body.bodyTag1</tag-class>

  <!-- 标签体内容,有标签体则设为jsp-->

  <body-content>jsp</body-content>

  <!-- 标签的属性声明-->

  <attribute>

   <name>countNum</name>

   <required>true</required>

   <rtexprvalue>true</rtexprvalue>

  </attribute>

  </tag>
  对于属性countNum的声明中,<required>设置为true,表示此属性为必输项;<rtexprvalue>设置为true,表示标签体支持运行时的表达式取值,如果为false则表示标签体为一个静态文本,默认情况下设置为true.

  (3)第三步:在Web应用的web.xml文件中声明标签库引用。

  同样,本例与实例108使用同一个tld文件,不必再修改。

  (4)第四步:在JSP页面中声明并调用标签。

  
UseBodyTag1.jsp

  <%@ taglib uri="/myTag" prefix="myTag" %>

  <%@ page contentType="text/html;charset=GB2312" %>

  <%@ page import="java.util.Date" %>

  <html>

    <head>

    <title>开发带有标签体的标签</title>

    </head> 

    <body>
  下面是应用这个带有属性的自定义标签的结果:

  
<br>

  <myTag:bodyTag1 countNum="6">

   现在的时间是:<%=new Date()%><br>

  </myTag:bodyTag1>

    </body>

  </html>
  该程序的运行结果如图13-4所示。

  


  开发嵌套的标签:haveChildTag

  实际工程中往往需要多个标签来配合完成一定的功能,嵌套的标签存在父子关系,其中,父为外层标签,子为内层标签。本实例将用两个简单的标签来演示,父标签则作出逻辑判断,如果isOutput属性为true,则输出实例108中的标签helloTag;如果为false,则不输出。

  (1)第一步:开发标签实现类。

  内层的标签helloTag在实例108中已有,此处不再列出。

  
haveChildTag.java

  package hello;

  import javax.servlet.jsp.tagext.BodyTagSupport;

    public class haveChildTag extends BodyTagSupport {

      private boolean isOutput;//是否输出子标签内容

      //----标签开始时调用此方法-------

      public int doStartTag(){

          if(isOutput)

              return EVAL_BODY_INCLUDE;

          else return SKIP_BODY;

      }

      //----标签结束时调用此方法-------

      public int doEndTag(){

          try{

              if(bodyContent!=null)

                bodyContent.writeOut(bodyContent.getEnclosingWriter());

          }catch(Exception e){

              System.out.println(e);

          }

          return EVAL_PAGE;

      }   

      public boolean getIsOutput() {

          return isOutput;

      }

      public void setIsOutput(boolean isOutput) {

          this.isOutput = isOutput;

      }

  }
  (2)第二步:编写标签描述tld文件。

  本例在myTag.tld文件中增加内容。在<taglib>与</taglib>之间增加的如下内容:

  
<!-- haveChildTag-->

  <tag>

  <!-- 标签名称-->

  <name>haveChildTag</name>

  <!-- 标签对应的处理类-->

  <tag-class>hello.haveChildTag</tag-class>

  <!-- 标签体内容,有标签体则设为jsp-->

  <body-content>jsp</body-content>

  <!-- 标签的属性声明-->

  <attribute>

   <name>isOutput</name>

   <required>true</required>

   <rtexprvalue>true</rtexprvalue>

  </attribute>

  </tag>
  (3)第三步:在Web应用的web.xml文件中声明标签库引用。

  同样,本例与本章前面的实例使用同一个tld文件,此处不必再修改。

  (4)第四步:在JSP页面中声明并调用标签。

  
useHaveChildTag.jsp

  <%@ taglib uri="/myTag" prefix="myTag" %>

  <%@ page contentType="text/html;charset=GB2312" %>

  <%@ page import="java.util.Date" %>

  <html>

    <head>

    <title>开发嵌套的标签</title>

    </head> 

    <body>

  输出子标签时的结果:<br>

  <myTag:haveChildTag isOutput="true">

   <myTag:helloTag/>

  </myTag:haveChildTag><br>

  不输出子标签时的结果:<br>

  <myTag:haveChildTag isOutput="false">

   <myTag:helloTag/>

  </myTag:haveChildTag><br>

    </body>

  </html>
  该程序的运行结果如图13-5所示。

  


  五、开发迭代的标签

  开发迭代的标签:iterateTag

  对于集合对象的Iterator类对象,在JSP的Java代码中需要用while循环或for循环来输出,难于维护,且可复用性不好,程序员总是在大量地做这样的工作,这时可以考虑用迭代的标签来开发,需要输出数据时只须在JSP页面中声明标签即可。

  开发迭代的标签,需要设计两个Java类:标签实现类和表示标签信息的类。本实例中标签实现类为iterateTag.java,表示标签信息的类为IterateTEI.java.开发迭代的标签可实现IterationTag接口,也可从TagSupport类或BodyTagSupport类继承,由于BodyTagSupport类继承自TagSupport类,而TagSupport类又实现了IterationTag接口,为简化开发,直接从BodyTagSupport类继承即可。

  (1)第一步:开发标签实现类和表示标签信息的类。

  
iterateTag.java

  package body;

  import java.util.Collection;

  import java.util.Iterator;

  import javax.servlet.jsp.tagext.BodyTagSupport;

  public class iterateTag extends BodyTagSupport{

      private String name;//在pageContext中标识的一个属性名

      private Iterator it;//要迭代的对象

      private String type;//it中对象的类型

      public void setCollection(Collection collection){

          if(collection.size()>0)

              it=erator();

      }

    

      //----标签开始时调用此方法-------

    public int doStartTag(){

        if(it==null) return SKIP_BODY;

        else return continueNext(it);

    }

    //----标签体执行完后调用此方法----

    public int doAfterBody(){

        return continueNext(it);

    }

    //----标签结束时调用此方法-------

      public int doEndTag(){

          try{

              if(bodyContent!=null)

                bodyContent.writeOut(bodyContent.getEnclosingWriter());

         }catch(Exception e){

              System.out.println(e);

          }

          return EVAL_PAGE;

      }  

      //----迭代----

      protected int continueNext(Iterator it){

          if(it.hasNext()){

              pageContext.setAttribute(name,it.next(),pageContext.PAGE_SCOPE);

              return EVAL_BODY_TAG;

          }else return SKIP_BODY;

      }

      public String getName() {

          return name;

      }

      public void setName(String name) {

          this.name = name;

      }

      public String getType() {

          return type;

      }

      public void setType(String type) {

          this.type = type;

      }

  }
  在标签实现类中,有3个属性:name、type和it.其中,name代表在pageContext中标识一个属性的名字;type代表待迭代内容的数据类型;it为要迭代的内容。在doStartTag()方法中,如果it不为null,就开始迭代,迭代时调用continueNext()方法。

  
IterateTEI.java

  package body;

  import javax.servlet.jsp.tagext.TagData;

  import javax.servlet.jsp.tagext.TagExtraInfo;

  import javax.servlet.jsp.tagext.VariableInfo;

  //----提供标签翻译时的一些相关信息----

  public class IterateTEI extends TagExtraInfo {

      public IterateTEI() {

          super();

      }

      public VariableInfo[] getVariableInfo(TagData data){

          return new VariableInfo[]{

                  new VariableInfo(data.getAttributeString("name"),

                          data.getAttributeString("type"),

                          true,VariableInfo.NESTED)

            };

        }

    }

  VariableInfo类中有几个常量,具体的含义为:

  NESTED:标签中的参数在标签开始到标签结束之间是有效的。

  AT_BEGIN:标签中的参数在标签开始到使用它的JSP页面结束是有效的。

  AT_END:标签中的参数在标签的结束到使用它的JSP页面结束是有效的。
  (2)第二步:编写标签描述tld文件。本例在myTag.tld文件中增加内容。在<taglib>与</taglib>之间增加如下内容:

  
     <!-- iterateTag-->

      <tag>

      <!-- 标签名称-->

      <name>iterateTag</name>

      <!-- 标签对应的处理类-->

      <tag-class>erateTag</tag-class>

      <tei-class>body.IterateTEI</tei-class>

      <!-- 标签体内容,有标签体则设为jsp-->

      <body-content>jsp</body-content>

      <!-- 标签的属性声明-->

      <attribute>

       <name>collection</name>

       <required>true</required>

       <rtexprvalue>true</rtexprvalue>

      </attribute>

      <attribute>

       <name>name</name>

       <required>true</required>

      </attribute>

      <attribute>

       <name>type</name>

       <required>true</required>

      </attribute>

      </tag>

  </taglib>
  (3)第三步:在Web应用的web.xml文件中声明标签库引用。同样,本例与本章前面的实例使用同一个tld文件,因此不必再修改。

  (4)第四步:在JSP页面中声明并调用标签。

  
<%@ taglib uri="/myTag" prefix="myTag" %>

  <%@ page contentType="text/html;charset=GB2312" %>

  <%@ page import="java.util.ArrayList"%>

    <head>

    <title>开发迭代的标签</title>

    </head> 

    <body>

    开发一个迭代的标签,输出结果:<br>

    <%//----------设置一个ArrayList对象的初始值----------

   ArrayList testCol=new ArrayList();

   testCol.add("邓佳容");

   testCol.add("黄婧");

   testCol.add("邓子云");

   request.setAttribute("testCol",testCol);

    %>

    <myTag:iterateTag name="testColOne" collection="<%=testCol%>" type="String">

     输出一个值:<%=testColOne.toString()%><br>

    </myTag:iterateTag>

    </body>

  </html>
    该程序的运行结果如图13-6所示。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: