JSP自定義標簽——簡單標簽(1)


  前面一篇博客介紹了自定義標簽的傳統標簽使用方式,但是我們會發現,使用傳統標簽非常的麻煩,而且接口還多,現在傳統標簽基本都沒用了,除了一些比較久的框架。Sun公司之后推出了一個新的標簽使用方式,稱之為簡單標簽。簡單標簽也作為JSP2.0以后的標准標簽使用方式,下面是一張傳統標簽和簡單標簽的對比,可以看到簡單標簽真的簡化了不少:

  

  與傳統標簽的使用步驟是類似的,需要滿足以下兩個步驟:

  ① 編寫一個實現SimpleTag接口(實際上我們更常的是繼承SimpleTagSupport接口的實現類從而免於覆寫所有的方法)的Java類,這個Java類也稱為標簽處理器類。

  ② 編寫標簽的TLD文件,用於指定標簽的URI和對標簽的聲明描述,這一點和EL函數時一樣的,TLD文件必須放置在web應用下的【WEB-INF】文件中,可以是除【classes】和【lib】目錄以外的任何子目錄中。TLD文件的模板可以從【Tomcat】--->【webapps】--->【examples】--->【WEB-INF】--->【jsp2】中有一個“jsp2-example-taglib.tld”文件復制首尾和其中的<Tag>標簽。

  注:在TLD文件中我們使用<tag>標簽來對每一個自定義標簽的Java類進行描述,其中每個<tag>標簽下還需要指定<body-content>的值,這個是描述標簽體的類型:對於簡單標簽使用:“empty”(無標簽體內容時) 或“scriptless” (有標簽體內容時)。

  注意:簡單標簽在JSP頁面中,標簽體內容中是不允許使用JSP腳本的。

 

  與傳統標簽需要使用doStartTag()方法和doEndTag()方法不同,簡單標簽只需要doTag()方法來處理標簽,所有的標簽體內容邏輯,迭代,是否執行標簽體內容等等都只需要調用doTag()方法即可。因此簡單標簽能和傳統標簽的bodyTagSupport能有一樣的功能,但是生命周期方式更簡單並且只有一個接口。

下圖是簡單標簽SimpleTag接口的所有方法:

  

  其中除了getParent方法以外,其他都是生命周期方法,這一點和傳統標簽類似。簡單自定義標簽的生命周期順序為:① 創建自定義標簽的實例對象 ---> ② setJspContext方法 ---> ③ setJspBody方法(如果有標簽體才調用) ---> ④ setParent方法(如果有父類自定義標簽才調用)---> ⑤ doTag方法 ---> ⑥ 該自定義標簽的實例對象將被垃圾回收器回收(與傳統自定義標簽不同,簡單標簽的標簽處理器類對象不會緩存)。

  下面簡單地介紹下這幾個生命周期方法:

  setJspContext(JspContext  pc)方法,JSP容器對簡單標簽進行實例化對象后,通過調用這個方法,將pageContext對象(pageContext是JspContext的子類)傳入標簽處理器類從而使得在標簽處理器類處理標簽和標簽體時(doTag)能通過這個對象獲取其他八大web對象。

  setJspBody(JspFragment jspBody)方法,是將標簽體內容封裝為一個JspFragment對象傳入給標簽處理器類,也就是說JspFragment對象就代表標簽體的內容。如果想要執行標簽體,只需要調用JspFragment對象的invoke(Writer out)方法傳入一個輸出流對象即可,或者如果往invoke方法中傳入的參數為null的話,默認參數為JspWriter對象,等效於invoke(this.getJspContext.getOut)。如果不調用invoke方法,那么就不會執行標簽體內容,另外可以隨意調用多次invoke方法。另外如果簡單標簽沒有標簽體內容,那么setJspBody不會被調用。

  setParent方法,只有在該自定義標簽嵌入在另一個自定義標簽中才會調用,記住父標簽必須也是自定義標簽才可以,如果父標簽只是簡單的HTML標簽那么該setParent方法不會被調用。

doTag()方法,由JSP容器來調用,通常是由我們開發人員來覆寫這個方法的實現,我們要使用標簽來完成任何功能的實現都在這個方法中。如果我們不想執行這個標簽后面余下的JSP頁面,那么只需要在這個方法內拋出一個“SkipPageException”異常即可。

  如果要想直接實現SimpleTag接口,那么在這個實現類中一定要有一個無參的構造函數。通常我們選擇繼承SimpleTag接口的實現類,也就是SimpleTagSupport類。繼承SimpleTagSupport類的話,繼承的子類中還可以使用SimpleTagSupport類給子類提供的方法獲取pageContext對象或者JspFragment對象:

  

 

例1:使用簡單標簽來控制是否執行標簽體內容

編寫標簽處理器類:

 1 package com.fjdingsd.simpletag;
 2 public class ShowTagBodyOrNot extends SimpleTagSupport {
 3     @Override
 4     public void doTag() throws JspException, IOException {
 5         
 6         JspFragment fragment = this.getJspBody();        
 7         fragment.invoke(this.getJspContext().getOut());
 8         //上面的代碼等效於fragment.invoke(null);
 9     }
10 }
View Code

在TLD文件中聲明描述標簽:

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
 5     version="2.0">
 6     <description>A tag library exercising SimpleTag handlers.</description>
 7     <tlib-version>1.0</tlib-version>
 8     <short-name>SimpleTagLibrary</short-name>
 9     <uri>simpletag</uri>
10    
11      <tag>
12         <name>showbody</name>
13         <tag-class>com.fjdingsd.simpletag.ShowTagBodyOrNot</tag-class>
14         <body-content>scriptless</body-content>
15     </tag>
16 
17 </taglib>
View Code

在JSP頁面中導入taglib指令:

    <%@ taglib uri="simpletag" prefix="simple" %>

最后就可以在JSP頁面的主體中使用剛才定義的簡單標簽了:

1     <simple:showbody>
2             銀魂
3        </simple:showbody>
View Code

在瀏覽器中觀察:

  

  分析:能顯示的原因,是因為在這個標簽中,將標簽體封裝成JspFragment對象,並且通過這個對象調用了invoke()方法,即執行標簽體內容,如果我們想控制標簽體內容不輸出顯示的話,只要不調用invoke()方法即可,修改例1的標簽處理器類:

1 public class ShowTagBodyOrNot extends SimpleTagSupport {
2     @Override
3     public void doTag() throws JspException, IOException {
4         
5         JspFragment fragment = this.getJspBody();    //這句代碼,或者甚至這個方法沒有都可以,都能控制標簽體內容不執行,要想執行必須要有JspFragment.invoke方法    
6         
7     }
8 }
View Code

  其他TLD文件等等內容都不變,則瀏覽器中不會對這個標簽顯示任何內容。

 

例2:使用簡單標簽來控制標簽體內容執行次數

編寫標簽處理器類:

 1 package com.fjdingsd.simpletag;
 2 public class LoopTagBody extends SimpleTagSupport {
 3     @Override
 4     public void doTag() throws JspException, IOException {    
 5         JspFragment fragment = this.getJspBody();
 6         for(int i=0;i<3;i++) {
 7             fragment.invoke(null);     //標簽體執行3次
 8         }
 9     }    
10 }
View Code

在TLD文件中描述(這里省略首尾,詳細內容請看例1):

1 <tag>
2       <name>loopbody</name>
3       <tag-class>com.fjdingsd.simpletag.LoopTagBody</tag-class>
4       <body-content>scriptless</body-content>
5  </tag>
View Code

在JSP頁面中導入taglib指令(此處略)后,在JSP頁面的主體中使用剛才定義的簡單標簽:

1     <simple:loopbody>
2             神樂  <br>
3       </simple:loopbody>
View Code

在瀏覽器中觀察:

  

 

例3:使用簡單標簽來修改標簽體內容再輸出(這里將標簽體內容中所有字母變為大寫)

  分析:要想使用簡單標簽來修改標簽體內容再輸出,需要先獲取標簽體對象(JspFragment),我們知道要想執行標簽體必須調用invoke(Writer out)方法,但是如果我們使用非緩沖的Writer輸出流,那么就直接輸出給瀏覽器了,無法達到修改目的,因此我們應該使用帶有緩沖流的字符流對象,將標簽體內容通過invoke方法先存入字符流,再從字符流中取出修改最后再輸出給瀏覽器。

編寫標簽處理器類:

 1 package com.fjdingsd.simpletag;
 2 public class ModifyTagBody extends SimpleTagSupport {
 3     @Override
 4     public void doTag() throws JspException, IOException {
 5         JspFragment fragment = this.getJspBody();
 6         StringWriter writer = new StringWriter();
 7         fragment.invoke(writer);
 8         
 9         String tagContent = writer.toString().toUpperCase();
10         this.getJspContext().getOut().write(tagContent);
11     }    
12 }
View Code

另:使用StringWriter緩沖流是因為StringWriter能夠獲得緩沖區中的值:

  

在TLD文件中描述(這里省略首尾,詳細內容請看例1):

1 <tag>
2         <name>modifybody</name>
3         <tag-class>com.fjdingsd.simpletag.ModifyTagBody</tag-class>
4         <body-content>scriptless</body-content>
5 </tag>
View Code

在JSP頁面中導入taglib指令(此處略)后,在JSP頁面的主體中使用剛才定義的簡單標簽:

1     <simple:modifybody>
2             long live sd
3      </simple:modifybody>
View Code

在瀏覽器中觀察:

  

 

例4:使用簡單標簽來控制便簽后余下的JSP頁面是否顯示

  若想使用簡單標簽來控制便簽后余下的JSP頁面不顯示,只需要在標簽處理器類的doTag方法中拋出“SkipPageException”異常即可。

 編寫標簽處理器類:

1 package com.fjdingsd.simpletag;
2 public class HideRemainJSP extends SimpleTagSupport {
3     @Override
4     public void doTag() throws JspException, IOException {
5         
6         throw new SkipPageException();
7     }
8 }
View Code

在TLD文件中描述(這里省略首尾,詳細內容請看例1):

1 <tag>
2           <name>hidepage</name>
3           <tag-class>com.fjdingsd.simpletag.HideRemainJSP</tag-class>
4           <body-content>empty</body-content>
5 </tag>
View Code

在JSP頁面中導入taglib指令(此處略)后,在JSP頁面的主體中使用剛才定義的簡單標簽:

 1 <simple:hidepage/>
 2 
 3 <!DOCTYPE HTML>
 4 <html>
 5   <head>
 6     <title>My JSP 'simpletagdemo.jsp' starting page</title>
 7   </head>
 8   
 9   <body>
10 。。。
11   </body>
12 </html>
View Code

  結果:我在JSP頁面最開始的地方使用了剛才自定義的簡單標簽,控制該標簽后的頁面不再執行,因此瀏覽器訪問該頁面中將只會看到空白頁面,包括頁面源碼也是為空。

 

 

 

 

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM