1. 程式人生 > >javabean 簡單例項

javabean 簡單例項

1.標籤(Tag):

  標籤是一種XML元素,通過標籤可以使JSP網頁變得簡潔並且易於維護,還可以方便地實現同一個JSP檔案支援多種語言版本。由於標籤是XML元素,所以它的名稱和屬性都是大小寫敏感的

  2.標籤庫(Tag library):

  由一系列功能相似、邏輯上互相聯絡的標籤構成的集合稱為標籤庫。

  3.標籤庫描述檔案(Tag Library Descriptor):

  標籤庫描述檔案是一個XML檔案,這個檔案提供了標籤庫中類和JSP中對標籤引用的對映關係。它是一個配置檔案,和web.xml是類似的。

  4.標籤處理類(Tag Handle Class):

  標籤處理類是一個Java類,這個類繼承了

TagSupport或者擴充套件了SimpleTag介面,通過這個類可以實現自定義JSP標籤的具體功能

  二、自定義JSP標籤的格式:

  1.為了使到JSP容器能夠使用標籤庫中的自定義行為,必須滿足以下兩個條件:

  1)從一個指定的標籤庫中識別出代表這種自定義行為的標籤

  2)找到實現這些自定義行為的具體類

  第一個必需條件-找出一個自定義行為屬於那個標籤庫-是由標籤指令的字首(Taglib Directive's Prefix)屬性完成,所以在同一個頁面中使用相同字首的元素都屬於這個標籤庫。每個標籤庫都定義了一個預設的字首,用在標籤庫的文件中或者頁面中插入自定義標籤。所以,你可以使用除了諸如jsp,jspx,java,servlet,sun,sunw(它們都是在JSP白皮書中指定的保留字)之類的字首。  

  uri屬性滿足了以上的第二個要求。為每個自定義行為找到對應的類。這個uri包含了一個字串,容器用它來定位TLD檔案。在TLD檔案中可以找到標籤庫中所有標籤處理類的名稱

  2.當web應用程式啟動時,容器從WEB-INF資料夾的目錄結構的META-INF搜尋所有以.tld結尾的檔案。也就是說它們會定位所有的TLD檔案。對於每個TLD檔案,容器會先獲取標籤庫的URI,然後為每個TLD檔案和對應的URI建立對映關係。

  在JSP頁面中,我們僅需通過使用帶有URI屬性值的標籤庫指令來和具體的標籤庫匹配

  三、自定義JSP標籤的處理過程:

  1.在JSP中引入標籤庫:  

  2.在JSP中使用標籤庫標籤

  3.Web容器根據第二個步驟中的prefix,獲得第一個步驟中宣告的taglib的uri屬性值

  4.Web容器根據uri屬性在web.xml找到對應的元素 

5.從元素中獲得對應的元素的值

 6.Web容器根據元素的值從WEB-INF/目錄下找到對應的.tld檔案 7.從.tld檔案中找到與tagname對應的元素 

8.湊元素中獲得對應的元素的值 

9.Web容器根據元素的值建立相應的tag handle class的例項 

10. Web容器呼叫這個例項的doStartTag/doEndTag方法完成相應的處理

  四、建立和使用一個Tag Library的基本步驟:

  1.建立標籤的處理類(Tag Handler Class)

  2.建立標籤庫描述檔案(Tag Library Descrptor File)

  3.在web.xml檔案中配置元素 4.在JSP檔案中引人標籤庫

  五、TagSupport類簡介:

  1.處理標籤的類必須擴充套件javax.servlet.jsp.TagSupport.

  2.TagSupport類的主要屬性:

  A.parent屬性:代表嵌套了當前標籤的上層標籤的處理類

  B.pageContex屬性:代表Web應用中的javax.servlet.jsp.PageContext物件

  3.JSP容器在呼叫doStartTag或者doEndTag方法前,會先呼叫setPageContext和setParent方法,設定pageContext和parent。因此在標籤處理類中可以直接訪問pageContext變數

  4.在TagSupport的構造方法中不能訪問pageContext成員變數,因為此時JSP容器還沒有呼叫

  setPageContext方法對pageContext進行初始化

  六、TagSupport處理標籤的方法:

  1.TagSupport類提供了兩個處理標籤的方法:

       public int doStartTag() throws JspException

       public int doEndTag() throws JspException

  2.doStartTag:但JSP容器遇到自定義標籤的起始標誌,就會呼叫doStartTag()方法。

   doStartTag()方法返回一個整數值,用來決定程式的後續流程。

  A.Tag.SKIP_BODY:表示?>…之間的內容被忽略

  B.Tag.EVAL_BODY_INCLUDE:表示標籤之間的內容被正常執行

  3.doEndTag:但JSP容器遇到自定義標籤的結束標誌,就會呼叫doEndTag()方法。doEndTag()方法也返回一個整數值,用來決定程式後續流程。

  A.Tag.SKIP_PAGE:表示立刻停止執行網頁,網頁上未處理的靜態內容和JSP程式均被忽略任何已有的輸出內容立刻返回到客戶的瀏覽器上。

  B.Tag_EVAL_PAGE:表示按照正常的流程繼續執行JSP網頁

  七、使用者自定義的標籤屬性:

  如果在標籤中還包含了自定義的屬性,那麼在標籤處理類中應該將這個屬性作為成員變數,並且分別提供設定和讀取屬性的方法。

  八、建立標籤處理類的步驟:

  1.建立包含JSP網頁靜態文字的檔案(即是要替換自定義JSP標籤的文字)

  2.在Web應用啟動時裝載靜態文字

  3.建立標籤處理類

  九、如何建立包含JSP網頁靜態文字的檔案:

  1.使用java.util.Properties類來存放要替換網頁中自定義JSP標籤的靜態文字

  2.Properties類代表了一系列屬性的集合,其例項既可以被儲存到流中,也可以從流中載入。這些文字以key/value的形式存放在WEB-INF目錄下,例如key=value,在屬性列表中這些key/value都是String型別的

  十、Properties類的常用API:

  1.setProperty(String key, String value):呼叫Hashtable類的put方法新增屬性

  2.getProperty(String key):獲取屬性列表中key對應的屬性值

  3.load(InputStream in):從輸入流物件InputStream中讀取屬性列表(Properties list)

  4.store(OutputStream out,String coMMent):使用適當的格式將屬性列表的屬性對寫入輸出流物件中,預設使用ISO-88590-1編碼格式,以行的方式處理輸入。屬性的key/value之間以”=、:”配對,以回車、換行分隔key/value配對

十一、ServletContext類的常用API

1、getContext(String uripath):返回伺服器中uripath所代表的ServletContext物件;

2、getInitParameter(String name):返回ServletConfig物件中name引數的值;

3、getMineType(String file):返回file引數代表的檔案的MIME型別;

4、getRequestDispatcher(String path):返回path代表的RequestDispacher物件;

5、getResourceAsStream(String path):以輸入流的形式返回path對應的資源,在輸入留中物件可以為任意形式的資料,path引數必須以“/”開始且相對於Context Root。

十二、如何使用ServletContxt讀取並儲存屬性檔案

1、建立java.util.Properties類物件;

2、獲取ServletContext物件;

3、將屬性檔案以輸入流的形式讀入到某個輸入流物件中;

4、將輸入流物件載入到Properties物件中;

5、將Properties物件儲存到ServletContext物件中。

十三、如何在Web應用啟動時裝載靜態文字

1、建立繼承了HttpServlet類的子類,在web.xml中配置這Servlet時設定load-on-startup屬性:

someclass 
somepackage.SomeClass1

2、在這個Servlet的init()方法中建立java.util.Properties類

3、獲取當前Web應用的ServletContext物件

4、將WEB-INF目錄下的屬性檔案讀入到輸入流InputStream中:

InputStream in = context.getResourceAsString("WEB-INF/someproperties.properties");

5、將輸入流載入到屬性物件中

ps.load(in);

6、將屬性物件儲存到上

context.setAttribute("attributeName",ps);

十四、如何建立標籤處理類

1、引入必需的資源

import javax.servlet.jsp.*; import javax.servlet.http.*; import java.util.*; import java.io.*;

2、繼承TagSupport類並覆蓋doStartTag()/doEndTag()方法

3、從ServletContext物件中獲取java.util.Properties物件

4、從Properties物件中獲取key對應的屬性值

5、對獲取的屬性進行相應的處理並輸出結果

十五、建立標籤庫描述檔案(Tag Library Descriptor)

1、標籤庫描述檔案,簡稱TLD,採用XML檔案格式,定義了使用者的標籤庫。TLD檔案中的元素可以分成3類:

A.標籤庫元素 
B.標籤元素 
C.標籤屬性元素

2、標籤庫元素用來設定標籤庫的相關資訊,它的常用屬性有:

A.shortname:指定Tag Library預設的字首名(prefix);

B.uri:設定Tag Library的惟一訪問表示符。

3、標籤元素用來定義一個標籤,它的常見屬性有:

A.name:設定Tag的名字;

B.tagclass:設定Tag的處理類;

C.bodycontent:設定標籤的主體(body)內容。

1)empty:表示標籤中沒有body; 
2)JSP:表示標籤的body中可以加入JSP程式程式碼; 
3)tagdependent:表示標籤中的內容由標籤自己去處理。

4、標籤屬性元素用來定義標籤的屬性,它的常見屬性有:

A.name:屬性名稱;
B.required:屬性是否必需的,預設為false; 
C.rtexprvalue:屬性值是否可以為request-time表示式,也就是類似於< %=…% >的表示式。

十六、在Web應用中使用標籤

1、如果Web應用中用到了自定義JSP標籤,則必須在web.xml檔案中加入元素,它用於宣告所引用的標籤所在的標籤庫

/sometaglib 
/WEB-INF/someTLD.tld

2、設定Tag Library的惟一標示符,在Web應用中將根據它來引用Tag Libray;

3、指定和Tag Library對應的TLD檔案的位置;

4、在JSP檔案中需要加入<!-- taglib% >指令來宣告對標籤庫的引用。例如: </p> <p><TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1> <TBODY> <TR> <TD class=code bgColor=#e6e6e6><PRE><% @ taglib prefix = &ldquo;somePrefix&rdquo; uri = "/someuri"-->

5、prefix表示在JSP網頁中引用這個標籤庫的標籤時的字首,uri用來指定Tag Library的識別符號,它必須和web.xml中的屬性保持一致。

----------------------------------------------------end-------------------------------

JSP自定義標籤開發入門例項

1.引言
本文將介紹JSP標籤的一些基本概念以及如何開發及使用自定義標籤。帶領大家邁上Java Web開發的又一新臺階.

2.什麼是自定義標籤
2.1.使用者自定義的Java語言元素,實質是執行一個或者兩個介面的JavaBean.
2.2.可以非常緊密的和JSP的表示邏輯聯絡在一起,又具有和普通JavaBean相同的業務邏輯處理能力.
2.3.當一個JSP頁面轉變為servlet時,其間的使用者自定義標籤轉化為操作一個稱為標籤hander的物件.
2.4.可操預設物件,處理表單資料,訪問資料庫以及其他企業級服務.

3.自定義標籤的特點
3.1.通過呼叫頁面實現傳遞定製.
3.2.訪問所有對JSP頁面可能的物件.
3.3.修改呼叫頁面生成的響應.
3.4.自定義標籤之間可以互相通訊.
3.5.在同一個JSP頁面中對標籤巢狀可以實現複雜互動.

4.例子:開發一個簡單的JSP標籤完整案例
4.1.建立標籤描述符檔案
在WEB-INF檔案下建立*.tld標籤描述符檔案:如
< taglib>
< tlibversion>1.0</tlibversion>
< jspversion>1.1</jspversion>
< shortname>eRedLab JSPTag Library</shortname>
< uri>/testTag</uri>
< info>自定義標籤測試</info>
< tag>
      <name>hello</name>
      <tagclass>com.eredlab.taglib.test.TestTld</tagclass>
      <bodycontent>empty</bodycontent>
      <info>自定義標籤測試</info>
      <attribute>
       <name>begin</name>
       <required>true</required>
      </attribute>
      <attribute>
       <name>end</name>
       <required>true</required>
      </attribute>
< /tag>
< /taglib>

4.2.建立標籤處理器
/**
* @desc 自定義標籤測試類 實現一個簡單的Hello World標籤
* @author      熊春 
* @version eRedLab 2007-9-10
*/
public class TestTld extends TagSupport{
//標籤屬性begin
private String begin = null;
//標籤屬性end
private String end = null;
//建構函式
public TestTld(){
  
}

/* 標籤初始方法 */
public int doStartTag() throws JspTagException{
      return super.EVAL_BODY_INCLUDE;
}

/* 標籤結束方法 */
public int doEndTag() throws JspTagException{
      JspWriter out = pageContext.getOut();
      String sum = begin + end;
      try{
       //標籤的返回值
       out.println(sum);
      }catch(IOException e){
       e.printStackTrace();
      }
      return super.SKIP_BODY;
}

/* 釋放資源 */
public void release(){
      super.release();
}
/********************************************
            屬性get()、set()方法
      *******************************************/
}

5.使用自定義JSP標籤
5.1.在Web.XML中載入標籤描述符檔案.
< !-- 載入標籤描述符檔案 -->
< taglib>
        <taglib-uri>/WEB-INF/test.tld</taglib-uri>
        <taglib-location>/WEB-INF/test.tld</taglib-location>
< /taglib>
5.2.在JSP中使用此標籤
< %@ taglib uri="/testTag" prefix="mytag"%>
< mytag:hello end="熊春!" begin="自定義標籤輸出流:Hello,"/>
< mytag:hello end="World!" begin="Hi,"/>
WEB頁面輸出結果如下:
自定義標籤輸出流:Hello,熊春! Hi,World! 
附圖1:JSP頁面編寫及程式碼輔助

附圖2.Web頁面輸出效果

 ------------------------------------------------end-------------------------------------------------------------------

jsp自定義標籤(taglib)編寫的原理和實現
一個tag就是一個普通的java類,它惟一特別之處是它必須繼承TagSupport或者 BodyTagSupport類。這兩個類提供了一些方法,負責jsp頁面和你編寫的類之間的互動,例如輸入,輸出。而這兩個類是由jsp容器提供的,無 須開發人員自己實現。換句話說,你只需把實現了業務邏輯的類繼承TagSupport或者BodyTagSupport,再做一些特別的工作,你的類就是 一個Tag。並且它自己負責和jsp 頁面的互動,不用你多操心。 

“特別的工作”通常有以下幾個步驟: 

[1]提供屬性的set方法,此後這個屬性就可以在jsp頁面設定。以jstl標籤為例 c:out value=""/,這個value就是jsp資料到tag之間的入口。所以tag裡面必須有一個setValue方法,具體的屬性可以不叫value。 例如setValue(String data){this.data = data;} 
這個“value”的名稱是在tld裡以attribute元素存在的。 
取什麼名字都可以,只需tag裡提供相應的set方法即可。 

[2]處理 doStartTag 或 doEndTag 。這兩個方法是 TagSupport提供的。 還是以c:out value=""/為例,當jsp解析這個標籤的時候,在“<”處觸發 doStartTag 事件,在“>”時觸發 doEndTag 事件。通常在 doStartTag 裡進行初始化,流程選擇操作,在 doEndTag 裡後續頁面輸出控制。 
[3]編寫tld檔案,就是把編寫的tag元件的資訊以xml形式告訴容器,它才好進一定步驟解釋tag元件 
[4]在jsp頁面匯入tld。這樣,你的jsp頁面就可以使用自己的tag元件了。 

通常你會發現自己絕大多數活動都集中在 doStartTag 或 doEndTag方法裡,如果在伺服器端處理標籤中的正文或則是巢狀標籤時的話,還是過問一下doAfterBody。 
一個簡單的例子:OutputTag 
Java程式碼
  1. package test;   
  2. import javax.servlet.jsp.JspException;   
  3. import javax.servlet.jsp.JspWriter;   
  4. import javax.servlet.jsp.tagext.TagSupport;   
  5. publicclass OutputTag extends TagSupport {   
  6. private String name=null;   
  7. publicvoid setName(String name) {   
  8. this.name = name;   
  9. }   
  10. publicint doEndTag() throws JspException   
  11. {   
  12. try {   
  13. JspWriter out = pageContext.getOut();   
  14. out.print("Hello! " + name);   
  15.   } catch (Exception e) { thrownew JspException(e); }   
  16. return EVAL_PAGE;   
  17. }   
  18. }   
Java程式碼
  1. package test;  import javax.servlet.jsp.JspException;  import javax.servlet.jsp.JspWriter;  import javax.servlet.jsp.tagext.TagSupport;   publicclass OutputTag extends TagSupport {  private String name=null;  publicvoid setName(String name) {  this.name = name;  }  publicint doEndTag() throws JspException  {  try {  JspWriter out = pageContext.getOut();  out.print("Hello! " + name);    } catch (Exception e) { thrownew JspException(e); }  return EVAL_PAGE;  }  }  


簡要說明: 
1 如何輸出到jsp頁面:呼叫JspWriter JspWriter out = pageContext.getOut();out.print......記住這個方法就可以了。 
2 輸出後如何作處理,函式會返回幾個值之一。EVAL_PAGE 表示tag已處理完畢,返回jsp頁面。還有幾個值,例如 EVAL_BODY_AGAIN 和EVAL_BODY_INCLUDE等 跟流程控制有關. 

編寫tld 
Java程式碼
  1. <?xml version="1.0" encoding="ISO-8859-1" ?>   
  2. <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN""http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">   
  3. <taglib>   
  4. <tlib-version>1.0</tlib-version>   
  5. <jsp-version>1.2</jsp-version>   
  6. <short-name>test</short-name>   
  7. <!--OutputTag-->   
  8. <tag>   
  9. <name>out</name>   
  10. <tag-class>test.OutputTag</tag-class>   
  11. <body-content>empty</body-content>   
  12. <attribute>   
  13. <name>name</name>   
  14. <required>false</required>   
  15. <rtexprvalue>false</rtexprvalue>   
  16. </attribute>   
  17. </tag>   
  18. </taglib>   
Java程式碼
  1. <?xml version="1.0" encoding="ISO-8859-1" ?>  <!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>1.0</tlib-version>  <jsp-version>1.2</jsp-version>  <short-name>test</short-name>  <!--OutputTag-->  <tag>  <name>out</name>  <tag-class>test.OutputTag</tag-class>  <body-content>empty</body-content>  <attribute>  <name>name</name>  <required>false</required>  <rtexprvalue>false</rtexprvalue>  </attribute>  </tag>  </taglib>  



在WEB-INF下新建tlds資料夾,把這個檔案取名為test.tld,放到tlds資料夾下。引用時的路徑應該這樣:WEB-INF\tlds\test.tld 

關於tld的簡單說明: 
short-name:taglib的名稱,也稱為字首。比如“c:out value=""/” 裡的“c” 
name:tag的名字。例如“c:out value=""/” 裡的"out”,我們的類也取名為out,由於有字首作區分,不會同其他庫的同名tag元件混淆 
tag-class:完整的tag元件路徑,記著帶包名 
body-content:指tag之間的內容。例如c:out value="" ...... /c 起始和關閉標籤之間就是body-content。由於沒有處理body-content ,所以上面設為empty,如果是巢狀標籤,或則是要在伺服器端處理標籤體的話,就是jsp了 
“attribute”裡的name:屬性名字。例如c:out value=""/裡的value。名字可任意取,只要類裡提供相應的set方法即可。 
required:是否必填屬性。 
rtexprvalue:是否支援執行時表示式取值就是是否可以<%=%>或則是${}方式傳值。 
這是tag的強大功能。 
編寫jsp頁面 

Java程式碼
  1. <%@ page language="java"%>   
  2. <%@ taglib uri="/WEB-INF/tlds/test.tld" prefix="test"%>   
  3. <html>   
  4. <body>   
  5. Test Tag: <test:out name="TEST"/>   
  6. </body>   
  7. </html>   
Java程式碼
  1. <%@ page language="java"%>  <%@ taglib uri="/WEB-INF/tlds/test.tld" prefix="test"%>  <html>  <body>  Test Tag: <test:out name="TEST"/>  </body>  </html>  



啟動伺服器,如果一切按照上面步驟的話,就能看到 Test Tag: Hello! TEST 字樣。最簡單的tag就這麼出來了。並不難,是不是? 
------------------------------------------------------------------ 
Tag系列的Interface裡定義的靜態int,通過他們也能一窺tag組鍵的執行流程,這幾個靜態值分別是: 
SKIP_BODY : 跳過了開始和結束標籤之間的程式碼,一般是在doStartTag中使用 
EVAL_BODY_INCLUDE :處理巢狀的標籤,一般是在doStartTag中使用,由負責處理標籤正文的tag介面提供 
EVAL_BODY_BUFFERED :對包含的內容進行解析 一般是在doStartTag中使用,由負責處理標籤正文的bodyTag介面提供,目的是通知jsp容器作好讀取正文的工作(建立一個body- content包裝正文和獲取存放操作結果的out物件,便於以後的操作和輸出). 
EVAL_BODY_AGAIN:處理標籤正文,巢狀標籤的iteratorTag介面的使用 
SKIP_PAGE : 忽略剩下的頁面,一般是在doEndTag中使用 
EVAL_PAGE : 繼續執行下面的頁, 一般是在doEndTag中使用

 --------------------------------------------end-----------------------------------------------

<!--正文-->

<!--判斷閱讀許可權--><!--判斷是否已經扣點-->

 一、JSP自定義標籤簡介

  標籤是一種XML元素,通過標籤可以使JSP網頁變得簡潔並且易於維護,還可以方便地實現同一個JSP檔案支援多種語言版本。由於標籤是XML元素,所以它的名稱和屬性都是大小寫敏感的

  標準JSP標籤是用來呼叫JavaBean元件的操作,處理定向請求以簡化JSP頁面開發與維護。JSP技術提供了一種封裝其它動態型別的機制——自定義標籤,它擴充套件了JSP語言。自定義標籤通常釋出在標籤庫中,該庫定義了一個自定義標籤集幷包含實現標籤的物件。

  自定義標籤是使用者定義的JSP語言元素。當JSP頁面包含一個自定義標籤時被轉化為servlet,標籤轉化為對稱為tag handler的物件的操作。接著當servlet執行時Web container呼叫那些操作。

  二、兩種標籤

  可以定義兩種型別的標籤:

javax.servlet.jsp.tagext.Tag 
javax.servlet.jsp.tagext.BodyTag

  有標籤體的標籤必須實現 BodyTag 介面。

<jsptag:map scope=“session” name=“tagMap”>
body
< /jsptag:map>

  也可能沒有標籤體:

<jsptag:map/>

  無標籤體的簡單標籤可以實現 Tag 介面。

  三、標籤處理程式

  int doStartTag() throws JspException---處理開始標籤

  int doEndTag() throws JspException---處理結束標籤

  Tag getParent()/void setParent(Tag t)---獲得/設定標籤的父標籤

  void setPageContext(PageContext pc)--- pageContext 屬性的 setter 方法

  void release() 釋放獲得的所有資源

 doStartTag()和doEndTag()方法的返回值說明:

  SKIP_BODY      表示不用處理標籤體,直接呼叫doEndTag()方法。

  SKIP_PAGE      忽略標籤後面的jsp(SUN企業級應用的首選)內容。

  EVAL_PAGE      處理標籤後,繼續處理jsp(SUN企業級應用的首選)後面的內容。

  EVAL_BODY_BUFFERED 表示需要處理標籤體,且需要重新建立一個緩衝(呼叫setBodyContent方法)。

  EVAL_BODY_INCLUDE  表示在現有的輸出流物件中處理標籤體,但繞過setBodyContent()和doInitBody()方法

  EVAL_BODY_AGAIN     對標籤體迴圈處理。(存在於javax.servlet.jsp.tagext.IterationTag介面中)

  實現javax.servlet.jsp.tagext.Tag介面

  擴充套件javax.servlet.jsp.tagext.TagSupport類

  TagSupport 類定義了 get/setParent() 和 setPageContext(),這與所有標籤處理程式幾乎相同。

  get/setParent() 方法允許標籤巢狀。

  TagSupport 類還定義了一個可以被子類使用的 pageContext 例項變數 (protected PageContext pageContext),這個變數是由 setPageContext() 方法設定的。

  在建立自定義標籤之前,需要建立一個 標籤處理程式。標籤處理程式是一個執行自定義標籤操作的 Java 物件。在使用自定義標籤時,要匯入一個 標籤庫 —— 即一組標籤/標籤處理程式對。通過在 Web 部署描述符中宣告庫匯入它,然後用指令 taglib 將它匯入 JSP 頁。

  如果 JSP 容器在轉換時遇到了自定義標籤,那麼它就檢查 標籤庫描述符(tag library descriptor) (TLD) 檔案以查詢相應的標籤處理程式。TLD 檔案對於自定義標籤處理程式,就像 Web 部署描述符對於 servlet 一樣。

  在執行時,JSP 頁生成的 servlet 得到對應於這一頁面所使用的標籤的標籤處理程式的一個例項。生成的 servlet 用傳遞給它的屬性初始化標籤處理程式。

  標籤處理程式實現了 生存週期 方法。生成的 servlet 用這些方法通知標籤處理程式應當啟動、停止或者重複自定義標籤操作。生成的 servlet 呼叫這些生存週期方法執行標籤的功能。

  四、TLD 檔案

  TLD 檔案的根元素是 taglib。taglib 描述了一個 標籤庫 —— 即一組標籤/標籤處理程式對。

  因為我們使用的是 JSP 版本 1.2,所以在這個例子中需要 tlib-version 和 short-name 元素。

  tlib-version 元素對應於標籤庫版本。

  jsp-version 對應於標籤庫所依賴的 JSP 技術的版本。

  short-name 元素定義了 IDE 和其他開發工具可以使用的標籤庫的簡單名。

  taglib 元素包含許多 tag 元素,標籤庫中每一個標籤有一個 tag 元素。

  在JSP中匯入TLD檔案:

<%@ taglib uri="firstTag" prefix="my"%>

  五、編寫自定義迭代標籤和el表示式呼叫類的靜態方法例項

  迴圈標籤體類:ForEach.java

 1import java.util.Collection;
 2import java.util.Iterator;
 3
 4import javax.servlet.jsp.JspException;
 5import javax.servlet.jsp.tagext.BodyContent;
 6import javax.servlet.jsp.tagext.BodyTagSupport;
 7
 8public class ForEach  extends BodyTagSupport
 9{
10  private String id;
11  private String collection;
12  private Iterator iter;
13  
14  public void setCollection(String collection)
15  {
16    this.collection = collection;
17  }
18  public void setId(String id)
19  {
20    this.id = id;
21  }
22  
23  //遇到開始標籤執行
24  public int doStartTag() throws JspException
25  {
26    Collection coll = (Collection) pageContext.findAttribute(collection);
27    // 表示如果未找到指定集合,則不用處理標籤體,直接呼叫doEndTag()方法。
28    if(coll==null||coll.isEmpty()) return SKIP_BODY;
29    
30    iter = coll.iterator();
31    pageContext.setAttribute(id, iter.next());
32    // 表示在現有的輸出流物件中處理標籤體,但繞過setBodyContent()和doInitBody()方法
33    // 這裡一定要返回EVAL_BODY_INCLUDE,否則標籤體的內容不會在網頁上輸出顯示
34    return EVAL_BODY_INCLUDE;
35  }
36  
37  //在doInitBody方法之前執行,在這裡被繞過不執行
38  @Override
39  public void setBodyContent(BodyContent arg0)
40  {
41    System.out.println("setBodyContent");
42    super.setBodyContent(arg0);
43  }
44  //此方法被繞過不會被執行
45  @Override
46  public void doInitBody() throws JspException
47  {
48    System.out.println("doInitBody");
49    super.doInitBody();
50  }
51  
52  //遇到標籤體執行
53  public int doAfterBody() throws JspException
54  {
55    if(iter.hasNext()) 
56    {
57      pageContext.setAttribute(id, iter.next());
58      return EVAL_BODY_AGAIN;// 如果集合中還有對像,則迴圈執行標籤體
59    }
60    return SKIP_BODY;//迭代完集合後,跳過標籤體,呼叫doEndTag()方法。
61  }
62  
63  //遇到結束標籤執行
64  public int doEndTag() throws JspException
65  {
66    System.out.println("doEndTag");
67    return EVAL_PAGE;
68  }
69
70}

 獲取VO屬性類:GetProperty.java

 1import java.lang.reflect.Method;
 2
 3import javax.servlet.jsp.JspException;
 4import javax.servlet.jsp.tagext.BodyTagSupport;
 5
 6public class GetProperty extends BodyTagSupport
 7{
 8
 9  private String name;
10  private String property;
11
12  public void setName(String name)
13  {
14    this.name = name;
15  }
16
17  public void setProperty(String property)
18  {
19    this.property = property;
20  }
21
22  @SuppressWarnings("unchecked")
23  public int doStartTag() throws JspException
24  {
25    try
26    {
27      Object obj = pageContext.findAttribute(name);
28      
29      if (obj == null) return SKIP_BODY;
30      
31      Class c = obj.getClass();
32      //構造GET方法名字 get+屬性名(屬性名第一個字母大寫)
33      String getMethodName = "get" + property.substring(0, 1).toUpperCase() 
34                              + property.substring(1, property.length());
35      Method getMethod = c.getMethod(getMethodName, new Class[]{});
36      
37      pageContext.getOut().print(getMethod.invoke(obj));
38      System.out.print(property + ":" + getMethod.invoke(obj) + "t");
39    } catch (Exception e)
40    {
41      e.printStackTrace();
42    }
43    return SKIP_BODY;
44  }
45
46  public int doEndTag() throws JspException
47  {
48    return EVAL_PAGE;
49  }
50}
51
52表示式直接訪問此類中靜態的方法:ELFunction.java
53public class ELFunction 
54{
55 public static int add( int i,int j )
56 {
57  return i+j;
58 }
59}

  寫一個測試用的VO類:UserVo.java

 1public class UserVo
 2{
 3  private String name;
 4  private String password;
 5  
 6  public String getName()
 7  {
 8    return name;
 9  }
10  public void setName(String name)
11  {
12    this.name = name;
13  }
14  public String getPassword()
15  {
16    return password;
17  }
18  public void setPassword(String password)
19  {
20    this.password = password;
21  }
22}

  建好TLD檔案tag.tld,放在WEB-INF目錄下

 1<?xml version="1.0" encoding="utf-8"?>
 2<taglib version="2.0"
 3 xmlns="http://java.sun.com/xml/ns/j2ee"
 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5 xmlns:shcemalocation="http://java.sun.com/xml/ns/j2ee 
 6 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 7 
 8 <description>自定義標籤</description>
 9 <display-name>JSTL core</display-name>
10 <tlib-version>1.1</tlib-version>
11 <short-name>firstLabel</short-name>
12 <uri>http://java.sun.com/jsp/jstl/core</uri>
13 
14 <!-- 建立自定義 迭代標籤 -->
15 <tag>
16  <name>forEach</name>
17  <tag-class>exercise.taglib.ForEach</tag-class>
18  <!-- 如果沒有標籤體,設定empty , 如果有標籤休必須設定JSP-->
19  <body-content>JSP</body-content>
20  <attribute>
21   <name>id</name>
22   <required>true</required><!-- 標識屬性是否是必須的 -->
23   <rtexprvalue>true</rtexprvalue><!-- 標識屬性值是否可以用表示式語言 -->
24  </attribute>
25  <attribute>
26   <name>collection</name>
27   <required>true</required>
28   <rtexprvalue>true</rtexprvalue>
29  </attribute>
30 </tag>
31 
32 <!-- 建立自定義獲得屬性標籤 -->
33 <tag>
34  <name>getProperty</name>
35  <tag-class>exercise.taglib.GetProperty</tag-class>
36  <body-content>empty</body-content>
37  <attribute>
38   <name>name</name>
39   <required>true</required>
40   <rtexprvalue>true</rtexprvalue>
41  </attribute>
42  <attribute>
43   <name>property</name>
44   <required>true</required>
45   <rtexprvalue>true</rtexprvalue>
46  </attribute>
47 </tag>
48 
49 <!-- 配置一個表示式呼叫 的函式 -->
50    <function>
51     <name>add</name><!-- 配置一個標籤,在JSP頁面通過引用字首呼叫 -->
52     <function-class>exercise.taglib.ELFunction</function-class><!-- 實現類 -->
53     <function-signature>int add(int,int)</function-signature><!-- 靜態的方法:包括返回型別,方法名,入參的型別 -->
54    </function>
55</taglib>

J2EE複習(六)JSP自定義標籤

<!--基本屬性-->

 一、JSP自定義標籤簡介

<!--正文-->

<!--判斷閱讀許可權--><!--判斷是否已經扣點-->

  在web.xml檔案中配置自定義標籤

1<jsp-config>
2 <taglib>
3  <taglib-uri>firstTag</taglib-uri>
4  <taglib-location>/WEB-INF/tag.tld</taglib-location>
5 </taglib>
6</jsp-config>

  在jsp檔案中使用標籤:tag.jsp

 1<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
 2<%@ taglib uri="firstTag" prefix="my"%>
 3
 4<jsp:useBean id="userVo1" class="exercise.vo.UserVo" scope="request">
 5  <jsp:setProperty name="userVo1" property="name" value="Hackiller"/>
 6  <jsp:setProperty name="userVo1" property="password" value="123"/>
 7</jsp:useBean>
 8
 9<jsp:useBean id="userVo2" class="exercise.vo.UserVo" scope="request">
10  <jsp:setProperty name="userVo2" property="name" value="YangYang"/>
11  <jsp:setProperty name="userVo2" property="password" value="456"/>
12</jsp:useBean>
13
14<%
15 List list = new ArrayList();
16 list.add(userVo1);
17 list.add(userVo2);
18 pageContext.setAttribute("voList",list);
19%>
20
21<html>
22  <head>
23    <title>My JSP 'tag.jsp' starting page</title>
24  </head>
25  
26  <body>
27    <h2 align="center">This is my JSP page:測試taglib.</h2> 
28    <hr>
29    
30   <h2>自定義迭代標籤:</h2>
31    <table>
32     <tr><td>姓名</td><td>密碼</td></tr>
33     <my:forEach collection="voList" id="uservo">
34      <tr>
35       <td><my:getProperty name="uservo" property="name"/></td>
36       <td><my:getProperty name="uservo" property="password"/></td>
37      </tr>
38     </my:forEach>
39    </table>
40    <hr>
41    
42    <h2>表示式呼叫類的靜態方法:</h2>
43    2+5=${my:add(2,5)} 
44  </body>
45</html>

--------------------------------------------------------------end----------------------

JSP自定義標籤

今天要實現的功能是useBean標籤。下表是它的一些屬性和用途。(我只選了個比較重要的屬性,並沒有實現所有屬性)
屬性 用途
id 給將要應用bean的變數一個名字,如果發現有相同id和scope的bean物件,則應用此物件而不會產生一個新的例示。
class 指明瞭bean的整個包名。
scope 表明了此bean的作用範圍,共有四個值:page, request, session, 和 application,預設的是page屬性,表明此bean只能應用於當前頁(儲存在當前頁的PageContext 中);request屬性表明此bean只能應用於當前的使用者請求中(儲存在ServletRequest物件中);session屬性表明此bean能應用於當前HttpSession生命週期內的所有頁面;application屬性值則表明此bean能應用於共享ServletContext的所有頁面。需要注意的是,當沒有具有相同的id和scope物件時,一個jsp:useBean 實體只能作用於一個新的例示中,反之,則作用於以前的物件,這時,在jsp:useBean標籤之間的任何jsp:setParameter和其它實體都將被忽略。
type 說明將要索引物件的變數型別,它必須與類名及父類名相匹配。記住,這個變數的名字是由id屬性值代替的。
beanName 給定此bean的名字,可以將其提供給bean的例示方法,只提供beanName和type而忽略class屬性的情況是允許的。
下面是標籤處理方法類:UseBean.java: import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.lang.reflect.*; // public class UseBean extends TagSupport{ //繼承自TagSupport類       private String scope;        private String type;        public UseBean(){super();}        /**         *設定屬性存取方法,這個方法由容器自動呼叫。setId()和getId()由系統自動實現         */        public void setScope(String s) {            this.scope = s;       }            public String getScope(){return this.scope;}        public void setType(String type){               this.type=type;        }        public String getType(){return this.type;}        /**         *覆蓋doStartTag方法         */         public int doStartTag() throws JspTagException          {               Object o = null;            // find the bean in the specified scope            if (scope.equals("page")) {

                     o = pageContext.getAttribute(getId(),PageContext.PAGE_SCOPE);

              } else if (scope.equals("request")) {

                     o = pageContext.getAttribute(getId(), PageContext.REQUEST_SCOPE);

              } else if (scope.equals("session")) {

                     o = pageContext.getAttribute(getId(), PageContext.SESSION_SCOPE);

              } else if (scope.equals("application")) {

                     o = pageContext.getAttribute(getId(), PageContext.APPLICATION_SCOPE);

           }               if(o==null)               {                      System.out.println("o is null!");                      try{                             Class u=Class.forName(type);                             o=u.newInstance();//無參構造方法                             System.out.println("create success!");                      }                      catch(Exception e){

                            throw new JspTagException("error to created a "+getId()+" object!");

                     }               }               pageContext.setAttribute(getId(), o); //儲存例項物件到上下文物件中            return EVAL_BODY_INCLUDE; //返回型別        } } 現在我們已經把物件例項放到pageContext裡了,是不是這樣就可以在JSP頁面中直接引用了?當然不是了,直接將JAVA物件放進pageContext中與在指令碼中直接引用是不同的。差別在於JSP容器要負責取得這個物件,以指令碼變數的形式提供給頁面。即JSP容器負責來維護指令碼變數與pageContext中相應物件的狀態。有兩種方法可以為自定義標籤來宣告指令碼變數。 一種是宣告variable,一種是通過TagExtraInfo類宣告變數。前者是JDK1.2後的方法,優點是比較方便。後者因為要再寫一個類檔案,所以顯得麻煩些,但更靈活,出於相容性與功能上的考慮,建議還是採用後者。(關於此類的詳細說明,請參考PPT文件)  import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*;  public class UseBeanTag extends TagExtraInfo {     public VariableInfo[] getVariableInfo(TagData data) {         return new VariableInfo[] {       new VariableInfo(             data.getId(),