javaweb学习总结(二十四):jsp传统标签开发
一、標(biāo)簽技術(shù)的API
1.1、標(biāo)簽技術(shù)的API類繼承關(guān)系
二、標(biāo)簽API簡單介紹
2.1、JspTag接口
JspTag接口是所有自定義標(biāo)簽的父接口,它是JSP2.0中新定義的一個標(biāo)記接口,沒有任何屬性和方法。JspTag接口有Tag和SimpleTag兩個直接子接口,JSP2.0以前的版本中只有Tag接口,所以把實現(xiàn)Tag接口的自定義標(biāo)簽也叫做傳統(tǒng)標(biāo)簽,把實現(xiàn)SimpleTag接口的自定義標(biāo)簽叫做簡單標(biāo)簽。
2.2、Tag接口
Tag接口是所有傳統(tǒng)標(biāo)簽的父接口,其中定義了兩個重要方法(doStartTag、doEndTag)方法和四個常量(EVAL_BODY_INCLUDE、SKIP_BODY、EVAL_PAGE、SKIP_PAGE),這兩個方法和四個常量的作用如下:
(1)WEB容器在解釋執(zhí)行JSP頁面的過程中,遇到自定義標(biāo)簽的開始標(biāo)記就會去調(diào)用標(biāo)簽處理器的doStartTag方法,doStartTag方法執(zhí)行完后可以向WEB容器返回常量EVAL_BODY_INCLUDE或SKIP_BODY。如果doStartTag方法返回EVAL_BODY_INCLUDE,WEB容器就會接著執(zhí)行自定義標(biāo)簽的標(biāo)簽體;如果doStartTag方法返回SKIP_BODY,WEB容器就會忽略自定義標(biāo)簽的標(biāo)簽體,直接解釋執(zhí)行自定義標(biāo)簽的結(jié)束標(biāo)記。
(2)WEB容器解釋執(zhí)行到自定義標(biāo)簽的結(jié)束標(biāo)記時,就會調(diào)用標(biāo)簽處理器的doEndTag方法,doEndTag方法執(zhí)行完后可以向WEB容器返回常量EVAL_PAGE或SKIP_PAGE。如果doEndTag方法返回常量EVAL_PAGE,WEB容器就會接著執(zhí)行JSP頁面中位于結(jié)束標(biāo)記后面的JSP代碼;如果doEndTag方法返回SKIP_PAGE,WEB容器就會忽略JSP頁面中位于結(jié)束標(biāo)記后面的所有內(nèi)容。
從doStartTag和doEndTag方法的作用和返回值的作用可以看出,開發(fā)自定義標(biāo)簽時可以在doStartTag方法和doEndTag方法體內(nèi)編寫合適的Java程序代碼來實現(xiàn)具體的功能,通過控制doStartTag方法和doEndTag方法的返回值,還可以告訴WEB容器是否執(zhí)行自定義標(biāo)簽中的標(biāo)簽體內(nèi)容和JSP頁面中位于自定義標(biāo)簽的結(jié)束標(biāo)記后面的內(nèi)容。
2.3、IterationTag接口
IterationTag接口繼承了Tag接口,并在Tag接口的基礎(chǔ)上增加了一個doAfterBody方法和一個EVAL_BODY_AGAIN常量。實現(xiàn)IterationTag接口的標(biāo)簽除了可以完成Tag接口所能完成的功能外,還能夠通知WEB容器是否重復(fù)執(zhí)行標(biāo)簽體內(nèi)容。對于實現(xiàn)了IterationTag接口的自定義標(biāo)簽,WEB容器在執(zhí)行完自定義標(biāo)簽的標(biāo)簽體后,將調(diào)用標(biāo)簽處理器的doAfterBody方法,doAfterBody方法可以向WEB容器返回常量EVAL_BODY_AGAIN或SKIP_BODY。如果doAfterBody方法返回EVAL_BODY_AGAIN,WEB容器就會把標(biāo)簽體內(nèi)容再重復(fù)執(zhí)行一次,執(zhí)行完后接著再調(diào)用doAfterBody方法,如此往復(fù),直到doAfterBody方法返回常量SKIP_BODY,WEB容器才會開始處理標(biāo)簽的結(jié)束標(biāo)記和調(diào)用doEndTag方法。
可見,開發(fā)自定義標(biāo)簽時,可以通過控制doAfterBody方法的返回值來告訴WEB容器是否重復(fù)執(zhí)行標(biāo)簽體內(nèi)容,從而達到循環(huán)處理標(biāo)簽體內(nèi)容的效果。例如,可以通過一個實現(xiàn)IterationTag接口的標(biāo)簽來迭代輸出一個集合中的所有元素,在標(biāo)簽體部分指定元素的輸出格式。
在JSP?API中也提供了IterationTag接口的默認(rèn)實現(xiàn)類TagSupport,我們在編寫自定義標(biāo)簽的標(biāo)簽處理器類時,可以繼承和擴展TagSupport類,這相比實現(xiàn)IterationTag接口將簡化開發(fā)工作。
2.4、BodyTag接口
BodyTag接口繼承了IterationTag接口,并在IterationTag接口的基礎(chǔ)上增加了兩個方法(setBodyContent、doInitBody)和一個EVAL_BODY_BUFFERED常量。實現(xiàn)BodyTag接口的標(biāo)簽除了可以完成IterationTag接口所能完成的功能,還可以對標(biāo)簽體內(nèi)容進行修改。對于實現(xiàn)了BodyTag接口的自定義標(biāo)簽,標(biāo)簽處理器的doStartTag方法不僅可以返回前面講解的常量EVAL_BODY_INCLUDE或SKIP_BODY,還可以返回常量EVAL_BODY_BUFFERED。如果doStartTag方法返回EVAL_BODY_BUFFERED,WEB容器就會創(chuàng)建一個專用于捕獲標(biāo)簽體運行結(jié)果的BodyContent對象,然后調(diào)用標(biāo)簽處理器的setBodyContent方法將BodyContent對象的引用傳遞給標(biāo)簽處理器,WEB容器接著將標(biāo)簽體的執(zhí)行結(jié)果寫入到BodyContent對象中。在標(biāo)簽處理器的后續(xù)事件方法中,可以通過先前保存的BodyContent對象的引用來獲取標(biāo)簽體的執(zhí)行結(jié)果,然后調(diào)用BodyContent對象特有的方法對BodyContent對象中的內(nèi)容(即標(biāo)簽體的執(zhí)行結(jié)果)進行修改和控制其輸出。
在JSP?API中也提供了BodyTag接口的實現(xiàn)類BodyTagSupport,我們在編寫能夠修改標(biāo)簽體內(nèi)容的自定義標(biāo)簽的標(biāo)簽處理器類時,可以繼承和擴展BodyTagSupport類,這相比實現(xiàn)BodyTag接口將簡化開發(fā)工作。
2.5、?SimpleTag接口
SimpleTag接口是JSP2.0中新增的一個標(biāo)簽接口。由于傳統(tǒng)標(biāo)簽使用三個標(biāo)簽接口來完成不同的功能,顯得過于繁瑣,不利于標(biāo)簽技術(shù)的推廣,因此,SUN公司為降低標(biāo)簽技術(shù)的學(xué)習(xí)難度,在JSP?2.0中定義了一個更為簡單、便于編寫和調(diào)用的SimpleTag接口。SimpleTag接口與傳統(tǒng)標(biāo)簽接口最大的區(qū)別在于,SimpleTag接口只定義了一個用于處理標(biāo)簽邏輯的doTag方法,該方法在WEB容器執(zhí)行自定義標(biāo)簽時調(diào)用,并且只被調(diào)用一次。那些使用傳統(tǒng)標(biāo)簽接口所完成的功能,例如是否執(zhí)行標(biāo)簽體、迭代標(biāo)簽體、對標(biāo)簽體內(nèi)容進行修改等功能都可以在doTag方法中完成。
在JSP?API中也提供了SimpleTag接口的實現(xiàn)類SimpleTagSupport,我們在編寫簡單標(biāo)簽時,可以繼承和擴展SimpleTagSupport類,這相比實現(xiàn)SimpleTag接口將簡化開發(fā)工作。
2.6、傳統(tǒng)標(biāo)簽接口中的各個方法可以返回的返回值說明
下圖列舉了Tag接口、IterationTag接口和BodyTag接口中的主要方法及它們分別可以返回的返回值的說明。
三、開發(fā)傳統(tǒng)標(biāo)簽實現(xiàn)頁面邏輯
開發(fā)人員在編寫Jsp頁面時,經(jīng)常還需要在頁面中引入一些邏輯,例如:
- 控制jsp頁面某一部分內(nèi)容是否執(zhí)行。
- 控制整個jsp頁面是否執(zhí)行。
- 控制jsp頁面內(nèi)容重復(fù)執(zhí)行。
- 修改jsp頁面內(nèi)容輸出。
自定義標(biāo)簽除了可以移除jsp頁面java代碼外,它也可以實現(xiàn)以上功能。
3.1、控制jsp頁面某一部分內(nèi)容是否執(zhí)行
編寫一個類實現(xiàn)tag接口,控制doStartTag()方法的返回值,如果這個方法返回EVAL_BODY_INCLUDE,則執(zhí)行標(biāo)簽體,如果返回SKIP_BODY,則不執(zhí)行標(biāo)簽體。
SUN公司針對tag接口提供了一個默認(rèn)的實現(xiàn)類TagSupport,TagSupport類中實現(xiàn)了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類實現(xiàn)了Tag接口,TagDemo1繼承TagSupport類 10 * 11 */ 12 public class TagDemo1 extends TagSupport { 13 14 /* 重寫doStartTag方法,控制標(biāo)簽體是否執(zhí)行 15 * @see javax.servlet.jsp.tagext.TagSupport#doStartTag() 16 */ 17 @Override 18 public int doStartTag() throws JspException { 19 //如果這個方法返回EVAL_BODY_INCLUDE,則執(zhí)行標(biāo)簽體,如果返回SKIP_BODY,則不執(zhí)行標(biāo)簽體 20 //return Tag.EVAL_BODY_INCLUDE; 21 return Tag.SKIP_BODY; 22 } 23 }在WEB-INF目錄下的tld文件中添加對該標(biāo)簽處理類的描述,如下:
1 <tag> 2 <name>demo1</name> 3 <tag-class>me.gacl.web.tag.TagDemo1</tag-class> 4 <!--demo1標(biāo)簽有標(biāo)簽體,所以這里的body-content設(shè)置為JSP--> 5 <body-content>JSP</body-content> 6 </tag>在jsp頁面中導(dǎo)入并使用自定義標(biāo)簽,如下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%--在jsp頁面中導(dǎo)入自定義標(biāo)簽庫 --%> 3 <%@taglib uri="/gacl" prefix="gacl" %> 4 <!DOCTYPE HTML> 5 <html> 6 <head> 7 <title>控制標(biāo)簽體是否執(zhí)行</title> 8 </head> 9 10 <body> 11 <%--在jsp頁面中使用自定義標(biāo)簽 demo1標(biāo)簽是帶有標(biāo)簽體的,標(biāo)簽體的內(nèi)容是"孤傲蒼狼"這幾個字符串--%> 12 <gacl:demo1> 13 孤傲蒼狼 14 </gacl:demo1> 15 </body> 16 </html>運行效果如下:
3.2、控制整個jsp頁面是否執(zhí)行
編寫一個類實現(xiàn)tag接口,控制doEndTag()方法的返回值,如果這個方法返回EVAL_PAGE,則執(zhí)行標(biāo)簽余下的jsp頁面,如果返回SKIP_PAGE,則不執(zhí)行余下的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類實現(xiàn)了Tag接口,TagDemo2繼承TagSupport類 10 */ 11 public class TagDemo2 extends TagSupport{ 12 13 /* 重寫doEndTag方法,控制jsp頁面是否執(zhí)行 14 * @see javax.servlet.jsp.tagext.TagSupport#doEndTag() 15 */ 16 @Override 17 public int doEndTag() throws JspException { 18 //如果這個方法返回EVAL_PAGE,則執(zhí)行標(biāo)簽余下的jsp頁面,如果返回SKIP_PAGE,則不執(zhí)行余下的jsp 19 return Tag.SKIP_PAGE; 20 //return Tag.EVAL_PAGE; 21 } 22 23 24 }在WEB-INF目錄下的tld文件中添加對該標(biāo)簽處理類的描述,如下:
1 <tag> 2 <name>demo2</name> 3 <tag-class>me.gacl.web.tag.TagDemo2</tag-class> 4 <!--demo2標(biāo)簽沒有標(biāo)簽體,所以這里的body-content設(shè)置為empty--> 5 <body-content>empty</body-content> 6 </tag>在jsp頁面中導(dǎo)入并使用自定義標(biāo)簽,如下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%--在jsp頁面中導(dǎo)入自定義標(biāo)簽庫 --%> 3 <%@taglib uri="/gacl" prefix="gacl" %> 4 <!DOCTYPE HTML> 5 <html> 6 <head> 7 <title>控制jsp頁面是否執(zhí)行</title> 8 </head> 9 10 <body> 11 <h1>jsp頁面的內(nèi)容1</h1> 12 <%--在jsp頁面中使用自定義標(biāo)簽 demo2標(biāo)簽是不帶標(biāo)簽體的--%> 13 <gacl:demo2/> 14 <h1>jsp頁面的內(nèi)容2</h1> 15 </body> 16 </html>運行效果如下:
3.3、控制jsp頁面內(nèi)容重復(fù)執(zhí)行
編寫一個類實現(xiàn)Iterationtag接口,控制doAfterBody()方法的返回值,如果這個方法返回EVAL_BODY_AGAIN, 則web服務(wù)器又執(zhí)行一次標(biāo)簽體,依次類推,一直執(zhí)行到doAfterBody方法返回SKIP_BODY,則標(biāo)簽體才不會重復(fù)執(zhí)行。
示例代碼如下:
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服務(wù)器又執(zhí)行一次標(biāo)簽體, 18 * 依次類推,一直執(zhí)行到doAfterBody方法返回SKIP_BODY,則標(biāo)簽體才不會重復(fù)執(zhí)行。 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文件中添加對該標(biāo)簽處理類的描述,如下:
1 <tag> 2 <name>demo3</name> 3 <tag-class>me.gacl.web.tag.TagDemo3</tag-class> 4 <!--demo3標(biāo)簽有標(biāo)簽體,所以這里的body-content設(shè)置為JSP--> 5 <body-content>JSP</body-content> 6 </tag>在jsp頁面中導(dǎo)入并使用自定義標(biāo)簽,如下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%--在jsp頁面中導(dǎo)入自定義標(biāo)簽庫 --%> 3 <%@taglib uri="/gacl" prefix="gacl" %> 4 <!DOCTYPE HTML> 5 <html> 6 <head> 7 <title>控制頁面內(nèi)容重復(fù)執(zhí)行5次</title> 8 </head> 9 10 <body> 11 <%--在jsp頁面中使用自定義標(biāo)簽 demo3標(biāo)簽--%> 12 <gacl:demo3> 13 <h3>jsp頁面的內(nèi)容</h3> 14 </gacl:demo3> 15 </body> 16 </html>運行效果如下:
3.4、修改jsp頁面內(nèi)容輸出
編寫一個類實現(xiàn)BodyTag接口,控制doStartTag()方法返回EVAL_BODY_BUFFERED,則web服務(wù)器會創(chuàng)建BodyContent對象捕獲標(biāo)簽體,然后在doEndTag()方法體內(nèi),得到代表標(biāo)簽體的bodyContent對象,從而就可以對標(biāo)簽體進行修改操作。
SUN公司針對BodyTag接口提供了一個默認(rèn)的實現(xiàn)類BodyTagSupport,BodyTagSupport類中實現(xiàn)了BodyTag接口的所有方法,因此我們可以編寫一個類繼承BodyTagSupport類,然后再根據(jù)需要重寫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類實現(xiàn)了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()得到代表標(biāo)簽體的bodyContent對象 29 BodyContent bodyContent = this.getBodyContent(); 30 //拿到標(biāo)簽體 31 String content = bodyContent.getString(); 32 //修改標(biāo)簽體里面的內(nèi)容,將標(biāo)簽體的內(nèi)容轉(zhuǎn)換成大寫 33 String result = content.toUpperCase(); 34 try { 35 //輸出修改后的內(nèi)容 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文件中添加對該標(biāo)簽處理類的描述,如下:
1 <tag> 2 <name>demo4</name> 3 <tag-class>me.gacl.web.tag.TagDemo4</tag-class> 4 <!--demo4標(biāo)簽有標(biāo)簽體,所以這里的body-content設(shè)置為JSP--> 5 <body-content>JSP</body-content> 6 </tag>在jsp頁面中導(dǎo)入并使用自定義標(biāo)簽,如下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%--在jsp頁面中導(dǎo)入自定義標(biāo)簽庫 --%> 3 <%@taglib uri="/gacl" prefix="gacl" %> 4 <!DOCTYPE HTML> 5 <html> 6 <head> 7 <title>修改jsp頁面內(nèi)容輸出</title> 8 </head> 9 10 <body> 11 <%--在jsp頁面中使用自定義標(biāo)簽 demo4標(biāo)簽--%> 12 <gacl:demo4> 13 <h3>xdp_gacl</h3> 14 </gacl:demo4> 15 </body> 16 </html>運行效果如下:
四、jsp傳統(tǒng)標(biāo)簽開發(fā)總結(jié)
在現(xiàn)在的jsp標(biāo)簽開發(fā)中,很少直接使用傳統(tǒng)標(biāo)簽來開發(fā)了,目前用得較多的都是簡單標(biāo)簽,所以Jsp的傳統(tǒng)標(biāo)簽開發(fā)了解一下即可,下一篇重點介紹jsp簡單標(biāo)簽的開發(fā)
總結(jié)
以上是生活随笔為你收集整理的javaweb学习总结(二十四):jsp传统标签开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javaweb学习总结(二十三):jsp
- 下一篇: javaweb学习总结(二十五):jsp