JSP中自訂標籤符的使用

來源:互聯網
上載者:User
js

摘要
   在JSP中有一種機制,可以讓你在JSP頁面中插入與HTML類似的標記。本文介紹JSP定製標記的基本概念和構成,以及如何開發和應用JSP定製標記。

 關鍵字
JSP,XML,TLD,標記符

什麼是標記
使用HTML語言我們可以這樣去編輯我們的網頁:

   <HTML>

    <HEAD>

<TITLE>

 HELLO  WORLD

</TITLE>

        </HEAD>

        <BODY>

HELLO WORLD

</BODY>

</HTML>

在這裡我們把</HEAD>,<TITLE>,<BODY>稱為標記。HTML 標籤( HTML Markup)是HTML文檔的控制語言,用於指定瀏覽器顯示和列印文檔的方式.它是用小於符號"<"和大於符號">"括起來的短語和符號,如 <Html>、</Body>等。許多HTMl標記以成對的方式出現,如<TITLE>< /TITLE>、<Body></Body> 等。在JSP中我們也可以定製自己的標記,以供JSP頁面使用,如下例所示

<!—login.jsp-->

<%@ taglib uri="/tlds/taglib.tld" prefix="tagclass" %>

<html>

      <head>

           <title>login</title>

      </head>

      <body>

        <tagclass:login width="200" height= "100" >

           </tagclass:login>

      </body>

</html>

在上例中</tagclass:login>就是一個JSP定製標記符。widtht、height是這個標記的屬性。<%@ taglib uri="/tlds/taglib.tld" prefix="tagclass" %>是一個標記庫定義指令,在稍後我們將會討論。在JSP中定製標記符,實質上就是以標記的形式封裝了一個俱有獨立功能的Java類。標記的使用減少了直接嵌入JSP頁面的Java代碼,方便了頁面的布局,並且有利於代碼的複用,提高了開發的效率。

JSP伺服器解析標記的過程
那麼當一個標記被嵌入JSP頁面後,JSP伺服器是如何對這個標記進行解析的呢?各對象的含義如下所示:

Client:   表示用戶端。

JSP-Server:JSP伺服器。

JSP-Page:JSP頁面。

TLD:   標記庫描述檔案,定義標記和標記的各種屬性和處理檔案等。

TagClass   標記處理常式

當一個使用者訪問一個JSP頁面時,這個請求被發送到JSP伺服器,JSP伺服器會根據這個請求去調用相應的頁面,如果這個頁面中有自訂的標記, JSP服務就會根據頁面指令<%@ taglib>去訪問TLD得到處理常式的相關資訊,接著調用該處理常式的構造器方法,啟動標記符處理常式,並讀取標記符的屬性和相應值。對每個沒有設定屬性的,調用相應的set方法。當標記符第一次使用時,它的任何屬性都不會做過設定,因此對每個屬性都調用set方法。屬性設定完以後,JSP伺服器調用處理常式的doStartTag(),然後再調用doEndTag()方法。最後JSP伺服器會繼續處理剩下的頁面,在頁面結尾調用release ()方法,清理佔用的所有資源。

TLD檔案
TLD(TLD:Tag Library Descriptor標記庫描述符)檔案,標準的XML格式的標記定義檔案,被用來存放標記符的資訊,下面就是一個典型的TLD檔案。

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!—XML的版本及其字元集-->

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

<!—此標記說明我們開始描述一個標記庫-->

  <tlibversion>1.0</tlibversion>

 <!—標記庫的版本-->

  <jspversion>1.1</jspversion>

 <!—所使用的JSP的版本-->

 <shortname>tagclass</shortname>

 <!—預設的名稱-->

  <tag>

     <name>login</name>

    <!—標記的名稱-->

<tagclass>

tagclass.login.login

<!—處理這個Tag的相應的類的名稱-->

</tagclass>

     <info>

      <!—對本標記符的描述-->

     </info>

<attribute>

<!—開始定義標記的屬性-->

          <name>height</name>

       <!—屬性的名稱-->

          <required>true</required>

       <!—表示這個屬性是不是必須的-->

          <rtexprvalue>true</rtexprvalue>

<!—表示這個屬性是否可以用JSP的程式段的結果輸出-->

      </attribute>

<attribute>

          <name>width</name>

          <required>true</required>

          <rtexprvalue>true</rtexprvalue>

      </attribute>

    </tag>

</taglib>

在這個TLD檔案中定義了只有一個標記符的標記符庫,這個名為login的標記符會調用一個Applet以驗證使用者的合法性。處理這個標記的類就是 tagclass.login.login。width、height是這個標記的兩個屬性。屬性是在使用標記符時作為參數發送的值。我們可以在上面的樣本中增加幾個標記,也可以為每個標記添加幾個屬性。我們開發標記符庫時不一定非要從頭開始,自己編寫一個全新TLD。我們可以使用某個整合的開發的環境,也可以修改上面的例子。

TagLib指令
那麼當JSP伺服器在解析一個標記符時,它是如何定義一個標記庫的呢?這就是TagLib指令的主要責任。

Taglib 指令

定義一個標記庫以及其自訂標籤的首碼.

JSP 文法

<%@ taglib uri="URIToTagLibrary" prefix="tagPrefix" %>

例子
<%@ taglib uri="/tlds/taglib.tld" prefix="tagclass" %>

<html>

      <head>

           <title>login</title>

      </head>

      <body>

        <tagclass:login width="200" height= "100" >

           </tagclass:login>

      </body>

</html>

描述

<% @ taglib %>指令聲明此JSP檔案使用了自訂的標記,同時引用標記庫,

也指定了他們的標記的首碼。 你必須在使用自訂標籤之前使用<% @ taglib %>指令。

屬性

uri="URIToTagLibrary" :Uniform Resource Identifier (URI)根據標記的首碼對自訂的標記進行唯一的命名,URI可以是一個相對或絕對的路徑。
  prefix="tagPrefix":在自訂標籤之前的首碼。如上例中的</tagclass:login>

標記符的處理常式(Tag handle)
我們還是以一個例子來看下如何?一個Tag handle。首先是看一下它的類圖:

讓我們再看一下它的代碼:

package  tagclass.login;

import javax.servlet.jsp.tagext.TagSupport;

import javax.servlet.jsp.*;

import java.io.*;

public class login extends TagSupport

{

      public login()

     {

             super();

      }

      public int doStartTag() throws JspTagException

     {

                JspWriter out = pageContext.getOut();

                try

                {

                        out.println("<APPLET CODEBASE=applet/login/ CODE=login.class width=200 height=100 > </APPLET>");

}

                catch(Exception e)

                {

                }

             return SKIP_BODY;

}

publicc int doEndTag()throws JsptagException

{

     return EVAL_PAGE;

}

       public void release()

       {

                 super.release();

       }

      public void setWidth(String language)

      {

             this.width = width;

      }

      public String getWidth()

      {

             return this.width;

      }

      public void setHeight(String height)

      {

          this.height=height;

      }

      public String getHeight()

      {

          return this.height;

      }

      private String width;

      private String height;

 }

從以上我們可以看出,實現一個簡單的標記符處理常式有幾個要求:①增加一個類,使之繼承 java.Servlet.jsp.tagext.TagSupport類。這個類提供了java.Servlet.jsp.tagext.Tag介面所要求的所有的方法。另外,還需要使用一些基本的API,使JSP容器能夠調用我們自己提供的標記符處理常式。②必須為每個標記符屬性分別建立一個 get<attribute>和set<attribute>方法,JSP容器需要使用這些方法處理常式傳遞參數。③要為標記符處理常式建立一個構造器和自毀器。JSP需要使用構造器啟動處理常式。自毀器是在realease()方法中定義的。在處理常式的生命週期結束時,需要調用自毀器釋放所佔用的資源。④建立兩個名為doStartTag()和doEndTag()的方法,執行具體的處理和輸出動作。這兩個方法是在處理自訂標籤符的起始位置和結束位置調用的。它們的傳回值是在Tag Interface裡定義的靜態int,這幾個靜態值分別是:

SKIP_BODY隱含0  :跳過了開始和結束標籤之間的代碼。

EVAL_BODY_INCLUDE隱含1:將body的內容輸出到存在的輸出資料流中

SKIP_PAGE隱含5 : 忽略剩下的頁面。

EVAL_PAGE隱含6:繼續執行下面的頁

  當然標記符也有它自己的缺點。很不方便的封裝過程,有限的功能。對於一些不太複雜和功能單一的邏輯描述,需要傳遞的參數要求不高時,使用JSP標記,要方便的多。對於大多數的商業邏輯應用程式,還是使用bean要好的多,也宜於servlet控制。

附錄:文章中所用樣本的完整代碼
JSP代碼:login.jsp
<%@ taglib uri="/tlds/taglib.tld" prefix="tagclass" %>

<html>

     <head>

           <title></title>

     </head>

     <body>

           <tagclass:login width="200" height= "100" >

           </tagclass:login>

     </body>

</html>

標記符描述庫:taglib.tld
<?xml version="1.0" encoding="ISO-8859-1" ?>

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

  <tlibversion>1.0</tlibversion>

  <jspversion>1.1</jspversion>

 <shortname>tagclass</shortname>

  <tag>

     <name>login</name>

<tagclass>

tagclass.login.login

</tagclass>

     <info>

    </info>

<attribute>

          <name>height</name>

          <required>true</required>

          <rtexprvalue>true</rtexprvalue>

      </attribute>

<attribute>

          <name>width</name>

          <required>true</required>

          <rtexprvalue>true</rtexprvalue>

      </attribute>

    </tag>

</taglib>

標記符處理常式:login.java
package  tagclass.login;

import javax.servlet.jsp.tagext.TagSupport;

import javax.servlet.jsp.*;

import java.io.*;

public class login extends TagSupport

{

      public login()

     {

             super();

      }

      public int doStartTag() throws JspTagException

     {

                JspWriter out = pageContext.getOut();

                try

                {

                        out.println("<APPLET CODEBASE=applet/login/ CODE=login.class width=200 height=100 > </APPLET>");

}

                catch(Exception e)

                {

                }

             return SKIP_BODY;

}

publicc int doEndTag()throws JsptagException

{

     return EVAL_PAGE;

}

       public void release()

       {

                 super.release();

       }

      public void setWidth(String language)

      {

             this.width = width;

      }

      public String getWidth()

      {

             return this.width;

      }

      public void setHeight(String height)

      {

          this.height=height;

      }

      public String getHeight()

      {

          return this.height;

      }

      private String width;

      private String height;

 }

標記符處理常式中所使用的Applet : login.java
import java.awt.*;

import java.awt.event.*;

import java.applet.*;

public class login extends Applet implements ActionListener

{

    private String s_username;

    private String s_userpassword;

    private Button b_ok;

    private Button b_register;

    private Label l_username;

    private Label l_userpassword;

    private TextField t_username;

    private TextField t_userpassword;

    private GridLayout g_gridlayout;

    public void init()

    {

       b_ok=new Button("ok");

       b_register=new Button("register");

       l_username= new Label("name");

       l_userpassword=new Label("password");

       t_username=new TextField();

       t_userpassword=new TextField();

       b_ok.addActionListener(this);

       b_register.addActionListener(this);

       g_gridlayout=new GridLayout(3,2,10,10);

       this.setLayout(g_gridlayout);

                //this.setBackground(Color.blue);

                add(l_username);

                add(t_username);

       add(l_userpassword);

       add(t_userpassword);

       add(b_ok);

       add(b_register);

    }

    public void actionPerformed(ActionEvent ev)

    {

           String s_label=ev.getActionCommand();

           if (s_label.equals("ok"))

           {

                 t_username.setText("name");

           }

           if (s_label.equals("register"))

           {

                 t_userpassword.setText("password");

           }

    }

    public void paint(Graphics g)

    {

     }

}



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.