裝載自:http://www.javashuo.com/article/p-fdezqsxm-dp.htmlhtml
JspTag接口是全部自定義標籤的父接口,它是JSP2.0中新定義的一個標記接口,沒有任何屬性和方法。JspTag接口有Tag和SimpleTag兩個直接子接口,JSP2.0之前的版本中只有Tag接口,因此把實現Tag接口的自定義標籤也叫作傳統標籤,把實現SimpleTag接口的自定義標籤叫作簡單標籤。java
Tag接口是全部傳統標籤的父接口,其中定義了兩個重要方法(doStartTag、doEndTag)方法和四個常量(EVAL_BODY_INCLUDE、SKIP_BODY、EVAL_PAGE、SKIP_PAGE),這兩個方法和四個常量的做用以下:web
(1)WEB容器在解釋執行JSP頁面的過程當中,遇到自定義標籤的開始標記就會去調用標籤處理器的doStartTag方法,doStartTag方法執行完後能夠向WEB容器返回常量EVAL_BODY_INCLUDE或SKIP_BODY。若是doStartTag方法返回EVAL_BODY_INCLUDE,WEB容器就會接着執行自定義標籤的標籤體;若是doStartTag方法返回SKIP_BODY,WEB容器就會忽略自定義標籤的標籤體,直接解釋執行自定義標籤的結束標記。服務器
(2)WEB容器解釋執行到自定義標籤的結束標記時,就會調用標籤處理器的doEndTag方法,doEndTag方法執行完後能夠向WEB容器返回常量EVAL_PAGE或SKIP_PAGE。若是doEndTag方法返回常量EVAL_PAGE,WEB容器就會接着執行JSP頁面中位於結束標記後面的JSP代碼;若是doEndTag方法返回SKIP_PAGE,WEB容器就會忽略JSP頁面中位於結束標記後面的全部內容。jsp
從doStartTag和doEndTag方法的做用和返回值的做用能夠看出,開發自定義標籤時能夠在doStartTag方法和doEndTag方法體內編寫合適的Java程序代碼來實現具體的功能,經過控制doStartTag方法和doEndTag方法的返回值,還能夠告訴WEB容器是否執行自定義標籤中的標籤體內容和JSP頁面中位於自定義標籤的結束標記後面的內容。ide
IterationTag接口繼承了Tag接口,並在Tag接口的基礎上增長了一個doAfterBody方法和一個EVAL_BODY_AGAIN常量。實現IterationTag接口的標籤除了能夠完成Tag接口所能完成的功能外,還可以通知WEB容器是否重複執行標籤體內容。對於實現了IterationTag接口的自定義標籤,WEB容器在執行完自定義標籤的標籤體後,將調用標籤處理器的doAfterBody方法,doAfterBody方法能夠向WEB容器返回常量EVAL_BODY_AGAIN或SKIP_BODY。若是doAfterBody方法返回EVAL_BODY_AGAIN,WEB容器就會把標籤體內容再重複執行一次,執行完後接着再調用doAfterBody方法,如此往復,直到doAfterBody方法返回常量SKIP_BODY,WEB容器纔會開始處理標籤的結束標記和調用doEndTag方法。學習
可見,開發自定義標籤時,能夠經過控制doAfterBody方法的返回值來告訴WEB容器是否重複執行標籤體內容,從而達到循環處理標籤體內容的效果。例如,能夠經過一個實現IterationTag接口的標籤來迭代輸出一個集合中的全部元素,在標籤體部分指定元素的輸出格式。this
在JSP API中也提供了IterationTag接口的默認實現類TagSupport,咱們在編寫自定義標籤的標籤處理器類時,能夠繼承和擴展TagSupport類,這相比實現IterationTag接口將簡化開發工做。spa
BodyTag接口繼承了IterationTag接口,並在IterationTag接口的基礎上增長了兩個方法(setBodyContent、doInitBody)和一個EVAL_BODY_BUFFERED常量。實現BodyTag接口的標籤除了能夠完成IterationTag接口所能完成的功能,還能夠對標籤體內容進行修改。對於實現了BodyTag接口的自定義標籤,標籤處理器的doStartTag方法不只能夠返回前面講解的常量EVAL_BODY_INCLUDE或SKIP_BODY,還能夠返回常量EVAL_BODY_BUFFERED。若是doStartTag方法返回EVAL_BODY_BUFFERED,WEB容器就會建立一個專用於捕獲標籤體運行結果的BodyContent對象,而後調用標籤處理器的setBodyContent方法將BodyContent對象的引用傳遞給標籤處理器,WEB容器接着將標籤體的執行結果寫入到BodyContent對象中。在標籤處理器的後續事件方法中,能夠經過先前保存的BodyContent對象的引用來獲取標籤體的執行結果,而後調用BodyContent對象特有的方法對BodyContent對象中的內容(即標籤體的執行結果)進行修改和控制其輸出。3d
在JSP API中也提供了BodyTag接口的實現類BodyTagSupport,咱們在編寫可以修改標籤體內容的自定義標籤的標籤處理器類時,能夠繼承和擴展BodyTagSupport類,這相比實現BodyTag接口將簡化開發工做。
SimpleTag接口是JSP2.0中新增的一個標籤接口。因爲傳統標籤使用三個標籤接口來完成不一樣的功能,顯得過於繁瑣,不利於標籤技術的推廣,所以,SUN公司爲下降標籤技術的學習難度,在JSP 2.0中定義了一個更爲簡單、便於編寫和調用的SimpleTag接口。SimpleTag接口與傳統標籤接口最大的區別在於,SimpleTag接口只定義了一個用於處理標籤邏輯的doTag方法,該方法在WEB容器執行自定義標籤時調用,而且只被調用一次。那些使用傳統標籤接口所完成的功能,例如是否執行標籤體、迭代標籤體、對標籤體內容進行修改等功能均可以在doTag方法中完成。
在JSP API中也提供了SimpleTag接口的實現類SimpleTagSupport,咱們在編寫簡單標籤時,能夠繼承和擴展SimpleTagSupport類,這相比實現SimpleTag接口將簡化開發工做。
下圖列舉了Tag接口、IterationTag接口和BodyTag接口中的主要方法及它們分別能夠返回的返回值的說明。
開發人員在編寫Jsp頁面時,常常還須要在頁面中引入一些邏輯,例如:
自定義標籤除了能夠移除jsp頁面java代碼外,它也能夠實現以上功能。
編寫一個類實現tag接口,控制doStartTag()方法的返回值,若是這個方法返回EVAL_BODY_INCLUDE,則執行標籤體,若是返回SKIP_BODY,則不執行標籤體。
SUN公司針對tag接口提供了一個默認的實現類TagSupport,TagSupport類中實現了tag接口的全部方法,所以咱們能夠編寫一個類繼承TagSupport類,而後再重寫doStartTag方法。
示例代碼以下:
TagDemo1.java
1 package me.gacl.web.tag; 2 3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.tagext.Tag; 5 import javax.servlet.jsp.tagext.TagSupport; 6 7 /** 8 * @author gacl 9 * TagSupport類實現了Tag接口,TagDemo1繼承TagSupport類 10 * 11 */ 12 public class TagDemo1 extends TagSupport { 13 14 /* 重寫doStartTag方法,控制標籤體是否執行 15 * @see javax.servlet.jsp.tagext.TagSupport#doStartTag() 16 */ 17 @Override 18 public int doStartTag() throws JspException { 19 //若是這個方法返回EVAL_BODY_INCLUDE,則執行標籤體,若是返回SKIP_BODY,則不執行標籤體 20 //return Tag.EVAL_BODY_INCLUDE; 21 return Tag.SKIP_BODY; 22 } 23 }
在WEB-INF目錄下的tld文件中添加對該標籤處理類的描述,以下:
1 <tag> 2 <name>demo1</name> 3 <tag-class>me.gacl.web.tag.TagDemo1</tag-class> 4 <!--demo1標籤有標籤體,因此這裏的body-content設置爲JSP--> 5 <body-content>JSP</body-content> 6 </tag>
在jsp頁面中導入並使用自定義標籤,以下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%--在jsp頁面中導入自定義標籤庫 --%> 3 <%@taglib uri="/gacl" prefix="gacl" %> 4 <!DOCTYPE HTML> 5 <html> 6 <head> 7 <title>控制標籤體是否執行</title> 8 </head> 9 10 <body> 11 <%--在jsp頁面中使用自定義標籤 demo1標籤是帶有標籤體的,標籤體的內容是"孤傲蒼狼"這幾個字符串--%> 12 <gacl:demo1> 13 孤傲蒼狼 14 </gacl:demo1> 15 </body> 16 </html>
運行效果以下:
編寫一個類實現tag接口,控制doEndTag()方法的返回值,若是這個方法返回EVAL_PAGE,則執行標籤餘下的jsp頁面,若是返回SKIP_PAGE,則不執行餘下的jsp。
示例代碼以下:
TagDemo2.java
1 package me.gacl.web.tag; 2 3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.tagext.Tag; 5 import javax.servlet.jsp.tagext.TagSupport; 6 7 /** 8 * @author gacl 9 * TagSupport類實現了Tag接口,TagDemo2繼承TagSupport類 10 */ 11 public class TagDemo2 extends TagSupport{ 12 13 /* 重寫doEndTag方法,控制jsp頁面是否執行 14 * @see javax.servlet.jsp.tagext.TagSupport#doEndTag() 15 */ 16 @Override 17 public int doEndTag() throws JspException { 18 //若是這個方法返回EVAL_PAGE,則執行標籤餘下的jsp頁面,若是返回SKIP_PAGE,則不執行餘下的jsp 19 return Tag.SKIP_PAGE; 20 //return Tag.EVAL_PAGE; 21 } 22 23 24 }
在WEB-INF目錄下的tld文件中添加對該標籤處理類的描述,以下:
1 <tag> 2 <name>demo2</name> 3 <tag-class>me.gacl.web.tag.TagDemo2</tag-class> 4 <!--demo2標籤沒有標籤體,因此這裏的body-content設置爲empty--> 5 <body-content>empty</body-content> 6 </tag>
在jsp頁面中導入並使用自定義標籤,以下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%--在jsp頁面中導入自定義標籤庫 --%> 3 <%@taglib uri="/gacl" prefix="gacl" %> 4 <!DOCTYPE HTML> 5 <html> 6 <head> 7 <title>控制jsp頁面是否執行</title> 8 </head> 9 10 <body> 11 <h1>jsp頁面的內容1</h1> 12 <%--在jsp頁面中使用自定義標籤 demo2標籤是不帶標籤體的--%> 13 <gacl:demo2/> 14 <h1>jsp頁面的內容2</h1> 15 </body> 16 </html>
運行效果以下:
編寫一個類實現Iterationtag接口,控制doAfterBody()方法的返回值,若是這個方法返回EVAL_BODY_AGAIN, 則web服務器又執行一次標籤體,依次類推,一直執行到doAfterBody方法返回SKIP_BODY,則標籤體纔不會重複執行。
示例代碼以下:
TagDemo3.java
1 package me.gacl.web.tag; 2 3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.tagext.IterationTag; 5 import javax.servlet.jsp.tagext.Tag; 6 import javax.servlet.jsp.tagext.TagSupport; 7 8 public class TagDemo3 extends TagSupport { 9 10 int x = 5; 11 @Override 12 public int doStartTag() throws JspException { 13 return Tag.EVAL_BODY_INCLUDE; 14 } 15 16 /* 控制doAfterBody()方法的返回值, 17 * 若是這個方法返回EVAL_BODY_AGAIN, 則web服務器又執行一次標籤體, 18 * 依次類推,一直執行到doAfterBody方法返回SKIP_BODY,則標籤體纔不會重複執行。 19 * @see javax.servlet.jsp.tagext.TagSupport#doAfterBody() 20 */ 21 @Override 22 public int doAfterBody() throws JspException { 23 x--; 24 if(x>0){ 25 return IterationTag.EVAL_BODY_AGAIN; 26 }else{ 27 return IterationTag.SKIP_BODY; 28 } 29 } 30 31 }
在WEB-INF目錄下的tld文件中添加對該標籤處理類的描述,以下:
1 <tag> 2 <name>demo3</name> 3 <tag-class>me.gacl.web.tag.TagDemo3</tag-class> 4 <!--demo3標籤有標籤體,因此這裏的body-content設置爲JSP--> 5 <body-content>JSP</body-content> 6 </tag>
在jsp頁面中導入並使用自定義標籤,以下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%--在jsp頁面中導入自定義標籤庫 --%> 3 <%@taglib uri="/gacl" prefix="gacl" %> 4 <!DOCTYPE HTML> 5 <html> 6 <head> 7 <title>控制頁面內容重複執行5次</title> 8 </head> 9 10 <body> 11 <%--在jsp頁面中使用自定義標籤 demo3標籤--%> 12 <gacl:demo3> 13 <h3>jsp頁面的內容</h3> 14 </gacl:demo3> 15 </body> 16 </html>
運行效果以下:
編寫一個類實現BodyTag接口,控制doStartTag()方法返回EVAL_BODY_BUFFERED,則web服務器會建立BodyContent對象捕獲標籤體,而後在doEndTag()方法體內,獲得表明標籤體的bodyContent對象,從而就能夠對標籤體進行修改操做。
SUN公司針對BodyTag接口提供了一個默認的實現類BodyTagSupport,BodyTagSupport類中實現了BodyTag接口的全部方法,所以咱們能夠編寫一個類繼承BodyTagSupport類,而後再根據須要重寫doStartTag方法和doEndTag()方法。
示例代碼以下:
TagDemo4.java
1 package me.gacl.web.tag; 2 3 import java.io.IOException; 4 5 import javax.servlet.jsp.JspException; 6 import javax.servlet.jsp.tagext.BodyContent; 7 import javax.servlet.jsp.tagext.BodyTag; 8 import javax.servlet.jsp.tagext.BodyTagSupport; 9 import javax.servlet.jsp.tagext.Tag; 10 11 /** 12 * @author gacl 13 * BodyTagSupport類實現了BodyTag接口接口,TagDemo4繼承 BodyTagSupport類 14 */ 15 public class TagDemo4 extends BodyTagSupport { 16 17 /* 控制doStartTag()方法返回EVAL_BODY_BUFFERED 18 * @see javax.servlet.jsp.tagext.BodyTagSupport#doStartTag() 19 */ 20 @Override 21 public int doStartTag() throws JspException { 22 return BodyTag.EVAL_BODY_BUFFERED; 23 } 24 25 @Override 26 public int doEndTag() throws JspException { 27 28 //this.getBodyContent()獲得表明標籤體的bodyContent對象 29 BodyContent bodyContent = this.getBodyContent(); 30 //拿到標籤體 31 String content = bodyContent.getString(); 32 //修改標籤體裏面的內容,將標籤體的內容轉換成大寫 33 String result = content.toUpperCase(); 34 try { 35 //輸出修改後的內容 36 this.pageContext.getOut().write(result); 37 } catch (IOException e) { 38 throw new RuntimeException(e); 39 } 40 41 return Tag.EVAL_PAGE; 42 } 43 }
在WEB-INF目錄下的tld文件中添加對該標籤處理類的描述,以下:
1 <tag> 2 <name>demo4</name> 3 <tag-class>me.gacl.web.tag.TagDemo4</tag-class> 4 <!--demo4標籤有標籤體,因此這裏的body-content設置爲JSP--> 5 <body-content>JSP</body-content> 6 </tag>
在jsp頁面中導入並使用自定義標籤,以下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%--在jsp頁面中導入自定義標籤庫 --%> 3 <%@taglib uri="/gacl" prefix="gacl" %> 4 <!DOCTYPE HTML> 5 <html> 6 <head> 7 <title>修改jsp頁面內容輸出</title> 8 </head> 9 10 <body> 11 <%--在jsp頁面中使用自定義標籤 demo4標籤--%> 12 <gacl:demo4> 13 <h3>xdp_gacl</h3> 14 </gacl:demo4> 15 </body> 16 </html>
運行效果以下:
在如今的jsp標籤開發中,不多直接使用傳統標籤來開發了,目前用得較多的都是簡單標籤,因此Jsp的傳統標籤開發瞭解一下便可,下一篇重點介紹jsp簡單標籤的開發