整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          JSP 自定義標簽

          自定義標簽是用戶定義的JSP語言元素。當JSP頁面包含一個自定義標簽時將被轉(zhuǎn)化為servlet,標簽轉(zhuǎn)化為對被 稱為tag handler的對象的操作,即當servlet執(zhí)行時Web container調(diào)用那些操作。

          JSP標簽擴展可以讓你創(chuàng)建新的標簽并且可以直接插入到一個JSP頁面。 JSP 2.0規(guī)范中引入Simple Tag Handlers來編寫這些自定義標記。

          你可以繼承SimpleTagSupport類并重寫的doTag()方法來開發(fā)一個最簡單的自定義標簽。

          創(chuàng)建"Hello"標簽

          接下來,我們想創(chuàng)建一個自定義標簽叫作<ex:Hello>,標簽格式為:

          <ex:Hello />

          要創(chuàng)建自定義的JSP標簽,你首先必須創(chuàng)建處理標簽的Java類。所以,讓我們創(chuàng)建一個HelloTag類,如下所示:

          package com.runoob;

          import javax.servlet.jsp.tagext.*;

          import javax.servlet.jsp.*;

          import java.io.*;

          public class HelloTag extends SimpleTagSupport {

          public void doTag() throws JspException, IOException {

          JspWriter out = getJspContext().getOut();

          out.println("Hello Custom Tag!");

          }

          }

          以下代碼重寫了doTag()方法,方法中使用了getJspContext()方法來獲取當前的JspContext對象,并將"Hello Custom Tag!"傳遞給JspWriter對象。

          編譯以上類,并將其復制到環(huán)境變量CLASSPATH目錄中。最后創(chuàng)建如下標簽庫:<Tomcat安裝目錄>webapps\ROOT\WEB-INF\custom.tld。

          <taglib>

          <tlib-version>1.0</tlib-version>

          <jsp-version>2.0</jsp-version>

          <short-name>Example TLD</short-name>

          <tag>

          <name>Hello</name>

          <tag-class>com.runoob.HelloTag</tag-class>

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

          </tag>

          </taglib>

          接下來,我們就可以在JSP文件中使用Hello標簽:

          <%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%>

          <html>

          <head>

          <title>A sample custom tag</title>

          </head>

          <body>

          <ex:Hello/>

          </body>

          </html>

          以上程序輸出結(jié)果為:

          Hello Custom Tag!

          訪問標簽體

          你可以像標準標簽庫一樣在標簽中包含消息內(nèi)容。如我們要在我們自定義的Hello中包含內(nèi)容,格式如下:

          <ex:Hello>

          This is message body

          </ex:Hello>

          我們可以修改標簽處理類文件,代碼如下:

          package com.runoob;

          import javax.servlet.jsp.tagext.*;

          import javax.servlet.jsp.*;

          import java.io.*;

          public class HelloTag extends SimpleTagSupport {

          StringWriter sw = new StringWriter();

          public void doTag()

          throws JspException, IOException

          {

          getJspBody().invoke(sw);

          getJspContext().getOut().println(sw.toString());

          }

          }

          接下來我們需要修改TLD文件,如下所示:

          <taglib>

          <tlib-version>1.0</tlib-version>

          <jsp-version>2.0</jsp-version>

          <short-name>Example TLD with Body</short-name>

          <tag>

          <name>Hello</name>

          <tag-class>com.runoob.HelloTag</tag-class>

          <body-content>scriptless</body-content>

          </tag>

          </taglib>

          現(xiàn)在我們可以在JSP使用修改后的標簽,如下所示:

          <%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%>

          <html>

          <head>

          <title>A sample custom tag</title>

          </head>

          <body>

          <ex:Hello>

          This is message body

          </ex:Hello>

          </body>

          </html>

          以上程序輸出結(jié)果如下所示:

          This is message body

          自定義標簽屬性

          你可以在自定義標準中設置各種屬性,要接收屬性,值自定義標簽類必須實現(xiàn)setter方法, JavaBean 中的setter方法如下所示:

          package com.runoob;

          import javax.servlet.jsp.tagext.*;

          import javax.servlet.jsp.*;

          import java.io.*;

          public class HelloTag extends SimpleTagSupport {

          private String message;

          public void setMessage(String msg) {

          this.message = msg;

          }

          StringWriter sw = new StringWriter();

          public void doTag()

          throws JspException, IOException

          {

          if (message != null) {

          /* 從屬性中使用消息 */

          JspWriter out = getJspContext().getOut();

          out.println( message );

          }

          else {

          /* 從內(nèi)容體中使用消息 */

          getJspBody().invoke(sw);

          getJspContext().getOut().println(sw.toString());

          }

          }

          }

          屬性的名稱是"message",所以setter方法是的setMessage()。現(xiàn)在讓我們在TLD文件中使用的<attribute>元素添加此屬性:

          <taglib>

          <tlib-version>1.0</tlib-version>

          <jsp-version>2.0</jsp-version>

          <short-name>Example TLD with Body</short-name>

          <tag>

          <name>Hello</name>

          <tag-class>com.runoob.HelloTag</tag-class>

          <body-content>scriptless</body-content>

          <attribute>

          <name>message</name>

          </attribute>

          </tag>

          </taglib>

          現(xiàn)在我們就可以在JSP文件中使用message屬性了,如下所示:

          <%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%>

          <html>

          <head>

          <title>A sample custom tag</title>

          </head>

          <body>

          <ex:Hello message="This is custom tag" />

          </body>

          </html>

          以上實例數(shù)據(jù)輸出結(jié)果為:

          This is custom tag

          你還可以包含以下屬性:

          屬性描述
          name定義屬性的名稱。每個標簽的是屬性名稱必須是唯一的。
          required指定屬性是否是必須的或者可選的,如果設置為false為可選。
          rtexprvalue聲明在運行表達式時,標簽屬性是否有效。
          type定義該屬性的Java類類型 。默認指定為 String
          description描述信息
          fragment如果聲明了該屬性,屬性值將被視為一個 JspFragment

          以下是指定相關的屬性實例:

          .....

          <attribute>

          <name>attribute_name</name>

          <required>false</required>

          <type>java.util.Date</type>

          <fragment>false</fragment>

          </attribute>

          .....

          如果你使用了兩個屬性,修改TLD文件,如下所示:

          .....

          <attribute>

          <name>attribute_name1</name>

          <required>false</required>

          <type>java.util.Boolean</type>

          <fragment>false</fragment>

          </attribute>

          <attribute>

          <name>attribute_name2</name>

          <required>true</required>

          <type>java.util.Date</type>

          </attribute>

          .....

          如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!

          然JSTL提供了很多豐富的標簽,但是在某些情況下,這些標簽還是不能夠滿足我們的業(yè)務需求,所以sun公司也提供了自定義標簽的功能,可以根據(jù)實際業(yè)務需求創(chuàng)建相應的標簽。自定義標簽在一些很老的項目中會經(jīng)常見到,因為那個時候基本上是基于Servlet和JSP進行項目的開發(fā),為了應對自身的項目需求,每個公司都會自己創(chuàng)建自己的標簽庫,從而簡化開發(fā),提高開發(fā)效率。

          自定義JSTL標簽只需要下面幾個步驟即可:

          1. 第一步:創(chuàng)建一個類,繼承自SimpleTagSupport類。
          2. 第二步:重寫doTag()方法,在這個方法中實現(xiàn)自定義標簽的處理邏輯。
          3. 第三步:在WEB-INF目錄下面,創(chuàng)建對應標簽的tld描述文件。
          4. 第四步:在JSP頁面中,通過<%@taglib%>指令自定義標簽即可。

          1.1、繼承SimpleTagSupport

          創(chuàng)建一個CustomTag類,繼承自SimpleTagSupport類,重寫doTag()方法。

          package com.gitcode.tag;
          
          import javax.servlet.jsp.JspException;
          import javax.servlet.jsp.JspWriter;
          import javax.servlet.jsp.tagext.JspFragment;
          import javax.servlet.jsp.tagext.SimpleTagSupport;
          import java.io.IOException;
          import java.io.StringWriter;
          
          /**
           * 自定義JSTL標簽
           */
          public class CustomTag extends SimpleTagSupport {
              /**
               * 自定義標簽屬性
               */
              private String content;
              /**
               * 標簽體內(nèi)容
               */
              private StringWriter body = new StringWriter();
          
              public void setContent(String content) {
                  this.content = content;
              }
          
              @Override
              public void doTag() throws JspException, IOException {
                  // 1、獲取輸出流對象
                  JspWriter writer = this.getJspContext().getOut();
                  if (content == null) {
                      // 屬性等于空,則直接獲取標簽之間的body內(nèi)容
                      JspFragment jspBody = this.getJspBody();
                      // 調(diào)用方法
                      jspBody.invoke(body);
                      // 輸出內(nèi)容
                      writer.println(body.toString());
                  } else {
                      // 如果屬性名稱不為空,則輸出屬性名稱的內(nèi)容
                      writer.println(content);
                  }
              }
          }

          1.2、創(chuàng)建tld描述文件

          在WEB-INF目錄下,我們創(chuàng)建一個tld目錄,用于保存我們自定義JSTL標簽的tld描述文件,tld描述文件中,需要編寫如下內(nèi)容:

          <?xml version="1.0" encoding="UTF-8" ?>
          
          <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
                  version="2.0">
          
              <tlib-version>1.1</tlib-version>
              <short-name>custom_tag</short-name>
          
              <tag>
                  <description>自定義JSTL標簽的描述內(nèi)容</description>
                  <name>custom_tag</name>
                  <tag-class>com.gitcode.tag.CustomTag</tag-class>
                  <!-- 標簽之間的內(nèi)容是腳本 -->
                  <body-content>scriptless</body-content>
                  <attribute>
                      <description>屬性的描述內(nèi)容</description>
                      <name>content</name>
                      <required>false</required>
                      <rtexprvalue>true</rtexprvalue>
                  </attribute>
              </tag>
          </taglib>

          如下圖所示:

          1.3、使用自定義標簽

          新建一個custom.jsp頁面,使用<%@taglib%>指令引入自定義標簽,如下所示:

          <%@ page contentType="text/html;charset=UTF-8" language="java" %>
          <%-- 引入標簽庫 --%>
          <%@ taglib prefix="custom_tag" uri="WEB-INF/tld/custom_tag.tld" %>
          <html>
          <head>
              <title>JSTL標簽庫之自定義標簽</title>
          </head>
          <body>
              <h3>JSTL標簽庫之自定義標簽</h3>
              <custom_tag:custom_tag content="content屬性內(nèi)容"></custom_tag:custom_tag>
          
              <h3>JSTL標簽庫之自定義標簽</h3>
              <custom_tag:custom_tag>
                  <ul>
                      <li>第一行</li>
                      <li>第二行</li>
                      <li>第三行</li>
                  </ul>
              </custom_tag:custom_tag>
          </body>
          </html>

          運行結(jié)果如下所示:

          需要注意的是,prefix屬性值必須和custom_tag.tld描述文件中的<short-name>標簽值保持一致,否則無法引用自定義標簽

          以上,就是JSTL自定義標簽的使用,創(chuàng)建自定義標簽可以將公用的代碼封裝起來,后續(xù)要使用的時候,可以減少代碼的開發(fā),從而提高開發(fā)效率。

          今天就到這里,未完待續(xù)~~

          實現(xiàn)自定義標簽時,有時需要對標簽體的內(nèi)容進行處理以后再向瀏覽器輸出,比如將小寫英文字母轉(zhuǎn)化為大寫,將HTML標簽進行轉(zhuǎn)義等。為了實現(xiàn)這樣的功能,JSP規(guī)范中它義了一個BodyTag接口,它繼承自IterationTag接口,并在IterationTag接口基礎上新增了兩個方法和一個靜態(tài)常量,具體如下。

          1. EVAL_BODY_BUFFERED常量

          如果標簽處理器類實現(xiàn)了BodyTag接口,它的doStartTag()方法除了可以返回SKIP_BODY和EVAL_BODY_INCLUDE常量之外,還可以返回EVAL_BODY_BUFFERED常量。當doStartTag()方法返回EVAL_BODY_BUFFERED常量時,JSP容器將會創(chuàng)建個javax.servlet.jsp.tagext.BodyContent對象,使用該對象來執(zhí)行標簽體。關于BodyContent類的用法,將在下面進行詳細的講解。

          2. setBodyContent(BodyContent b)方法

          當且僅當doStartTag()方法返回EVAL_BODY_BUFFERED常量時,JSP容器才會調(diào)用setBodyContent()方法,通過該方法將BodyContent對象傳遞給標簽處理器類使用。

          3. dolnitBody()方法

          JSP容器在調(diào)用setBodyContent()方法后會調(diào)用doInitBody()方法來完成些初始化工作,該方法的調(diào)用在標簽體執(zhí)行之前。

          其中,最重要的是setBodyContent()方法。為了幫助大家更好地理解BodyTag接口處理標簽內(nèi)容的方式,有必要對BodyContent類進行詳細講解。

          BodyContent類是JspWriter類的子類,它在JspWriter的基礎上增加了一個用于存儲數(shù)據(jù)的緩沖區(qū)(確切地說緩沖區(qū)是在BodyContent的子類org.apache.jasper.runtime.BodyContentImple中定義的),當調(diào)用BodyContent對象的方法寫數(shù)據(jù)時,數(shù)據(jù)將被寫人到BodyContent內(nèi)部的緩沖區(qū)中。

          明白了BodyContent類的這個特點,就不難理解JSP容器是如何利用BodyContent對象來處理標簽體內(nèi)容了。當標簽處理器類的doStartTag()方法返回EVAL_BODY_BUFFERED常量時,JSP容器會創(chuàng)建一個BodyContent對象,然后調(diào)用該對象的write()方法將標簽體的內(nèi)容寫人BodyContent對象的緩沖區(qū)中,開發(fā)者只要能夠訪問BodyContent緩沖區(qū)的內(nèi)容,就能對標簽體的內(nèi)容進行處理。在BodyContent類中定義了一些用于訪問緩沖區(qū)內(nèi)容的方法,具體如下表所示。

          BodyContent類的常用方法

          方法聲明

          功能描述

          String getString()

          以字符串的形式返回BodyContent對象緩沖區(qū)中保存的數(shù)據(jù)

          Reader getReader()

          返回一個關聯(lián)BodyContent對象緩沖區(qū)中數(shù)據(jù)的Reader對
          象,通過Reader對象可以讀取緩沖區(qū)中的數(shù)據(jù)

          void clearBody()

          用于清空BodyContent對象緩沖區(qū)中的內(nèi)容

          JspWriter getEnclosingWriter()

          用于返回BodyContent對象中關聯(lián)的JspWriter對象。當JSP容器創(chuàng)建BodyContent對象后,PageContext對象中的"out"屬性不再指向JSP的隱式對象,而是指向新創(chuàng)建的BodyContent對象。同時,在BodyContent對象中會用一個JspWriter類型的成員變量enclosingWriter記住原來的隱式對象,getEnclosingWriter()方 法返回的就是原始的JSP隱式對象

          writerOut(Writer out)

          用于將BodyContent對象中的內(nèi)容寫人到指定的輸出流

          在上表列舉的所有方法中,其中g(shù)etEnclosingWriter()方法最難理解,但是,只需要記住該方法的返回值為out即可。

          除了BodyContent類外,在BodyTag接口還會涉及很多常量和方法,為了讓大家更好地掌握標簽處理器的執(zhí)行流程,接下來通過一張圖來描述,具體如下圖所示。

          標簽處理器的執(zhí)行流程

          上圖中清楚地描述了JSP容器執(zhí)行標簽處理器的過程。其中,release()方法之所以使用用虛線,是因為這個方法不會在標簽處理器每次執(zhí)行都被JSP容器調(diào)用,只有當標簽處理器對象作為垃圾被回收之前它才會被調(diào)用。傳統(tǒng)標簽的處理器是單例的,只會被創(chuàng)建和銷毀一次。

          接下來,通過實現(xiàn)自定義標簽,學習如何使用BodyTag接口將標簽體中的小寫英文字母轉(zhuǎn)換為大寫,具體步驟如下。

          (1)編寫標簽處理器類ToUpperCase.java。

          JSP規(guī)范中定義了一個類BodyTagSupport實現(xiàn)了BodyTag接口,為了簡化程序的編寫,標簽處理器類ToUpperCase.java只需要繼承BodyTagSupport類即可。ToUpperCase.java類的實現(xiàn)代碼如下例所示。

          package cn.itcast.chapter09.classisctag;
          import java.io.IOException;
          import javax.servlet.jsp.JspException;
          import javax.servlet.jsp.tagext.BodyTagSupport;
          public class ToUpperCase extends BodyTagSupport {
              //定義doEndTag()方法
              public int doEndTag() throws JspException {
                  //獲取級沖區(qū)中數(shù)據(jù)
                  String content = getBodyContent().getString();
                  //將數(shù)據(jù)轉(zhuǎn)為大寫
                  content = content.toUpperCase();
                  try{
                      //輸出數(shù)據(jù)內(nèi)容(兩種方式均可)
                      //pageContext.getout().write(content);
                      bodyContent.getEnclosingWriter().write(content);
                  } catch(IOException e){
                      e.printStackTrace();
                      return super.doEndTag();
                  }
          }

          由于BodyTagSupport類中的doStartTag()方法默認返回EVAL_BODY_BUFFERED常量,JSP容器會在執(zhí)行標簽體之前創(chuàng)建BodyContent對象,然后將標簽體內(nèi)容通過setBodyContent()方法設置給BodyContent對象。因此在上面案例中的doEndTag()方法中可以直接使用getBodyContent()方法的getString()方法獲得寫人到BodyContent緩沖區(qū)中的內(nèi)容,然后將其轉(zhuǎn)換為大寫,通過調(diào)用getEnclosingWriter()方法獲取到out對象,將內(nèi)容輸出到瀏覽器中。

          注意:不能直接使用doStartTag()方法的原因是,執(zhí)行doStartTag()方法時,BodyContent對象中還沒有緩存標簽體的內(nèi)容,因此通過getBodyContent()方法還無法獲得標簽的內(nèi)容。

          (2)注冊標簽處理器類。

          在mytag.tld文件中增加一個Tag元素,對標簽處理器類進行注冊,注冊信息如下所示。

          <tag>
              <name>toUpperCase</name>
              <tag-class> cn.itcast.chapter09.classisctag.ToUpperCase</tag-class>
              <body-content>JSP</body-content>
          </tag>

          (3)編寫JSP頁面toUpperCase.jsp

          在JSP頁面中使用標簽,在標簽體中寫人26個小寫的英文字母,如下例所示。

          <%@page language="java" pageEncoding="GBK"%>
          <%@taglib uri= "http://www.itcast.cn" prefix="itcast"%>
          <html>
              <head>
              <title>HelloWorld Tag</title>
          </head>
          <body>
              <itcast: toUpperCase>
                  abcde fghij klmnopqrstuvwxyz
              </itcast:toUpperCase>
          </body>
          </html>

          (4)啟動Tomcat服務器,在瀏覽器地址欄中輸人URL地址“http://localhost:8080/chapter09/toUpperCase.jsp”訪問toUpperCase.jsp頁面,從運行結(jié)果可以看出,自定義標簽成功地將標簽體中的小寫英文字母轉(zhuǎn)換為大寫。


          主站蜘蛛池模板: 无码日韩精品一区二区三区免费| 国产主播在线一区| 琪琪see色原网一区二区| 黄桃AV无码免费一区二区三区| 国产乱码精品一区二区三区中文 | 亚洲一区二区三区无码国产 | 亚洲A∨无码一区二区三区 | 亚洲无线码一区二区三区| 日韩国产免费一区二区三区| 国产在线aaa片一区二区99| 在线观看日韩一区| 冲田杏梨AV一区二区三区 | 免费一区二区三区| 精品国产毛片一区二区无码| 夜色阁亚洲一区二区三区| AV鲁丝一区鲁丝二区鲁丝三区 | 一区二区三区在线| 精品一区二区三区免费毛片| 亚洲Av永久无码精品一区二区| 精品欧洲av无码一区二区三区| 久久一区不卡中文字幕| 亚洲一区爱区精品无码| 久久婷婷色综合一区二区| 色综合视频一区二区三区| 在线一区二区观看| 国产一区二区精品在线观看| 国产精品免费综合一区视频| 国产一区二区福利久久| 视频一区二区中文字幕| 变态拳头交视频一区二区| 一区二区三区无码视频免费福利| 亚洲综合一区二区精品导航 | 本免费AV无码专区一区| 中文字幕一区二区三| 亲子乱AV视频一区二区| 99久久国产精品免费一区二区| 亚洲一区二区三区91| 欧洲无码一区二区三区在线观看 | 精品一区二区三区四区电影| 免费无码一区二区| 国产内射999视频一区|