自定義標(biāo)簽和新特性_第1頁
自定義標(biāo)簽和新特性_第2頁
自定義標(biāo)簽和新特性_第3頁
自定義標(biāo)簽和新特性_第4頁
自定義標(biāo)簽和新特性_第5頁
已閱讀5頁,還剩100頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

自定義標(biāo)簽和新特性第一頁,共105頁。網(wǎng)絡(luò)編程第7章自定義標(biāo)簽和新特性第二頁,共105頁。主題章節(jié)內(nèi)容本章小結(jié)課后習(xí)題課外讀物第三頁,共105頁。章節(jié)內(nèi)容7.0引言7.1自定義標(biāo)簽7.2JSP2.0的新特性第四頁,共105頁。7.0引言為了減少JSP中的腳本,JavaEE規(guī)范允許開發(fā)人員自定義標(biāo)簽。

從JSP1.1開始增加了自定義標(biāo)簽庫規(guī)范,自定義標(biāo)簽庫是一種非常優(yōu)秀的表現(xiàn)層組件技術(shù)。通過使用自定義標(biāo)簽庫,可以在簡單的標(biāo)簽中封裝復(fù)雜的功能。在本章的內(nèi)容中,將詳細講解JSP中自定義標(biāo)簽和JSP2新特性的基本知識,為后續(xù)的學(xué)習(xí)打下基礎(chǔ)。第五頁,共105頁。7.1.1自定義標(biāo)簽概述7.1.2自定義標(biāo)簽種類7.1.3自定義標(biāo)簽的開發(fā)7.1自定義標(biāo)簽第六頁,共105頁。7.1.1自定義標(biāo)簽概述自定義標(biāo)簽是用戶定義的JSP語言元素。當(dāng)JSP頁面包含一個自定義標(biāo)簽時被轉(zhuǎn)化為servlet,標(biāo)簽轉(zhuǎn)化為對應(yīng)標(biāo)簽處理器(taghandler)對象的操作。接著當(dāng)servlet執(zhí)行時Web容器(container)調(diào)用那些操作。自定義標(biāo)簽特點可以通過調(diào)用頁面?zhèn)鬟f的屬性進行自定義??梢栽L問JSP頁面上可能的所有對象??梢孕薷挠烧{(diào)用頁面產(chǎn)生的響應(yīng)。可以相互間通信。你可以創(chuàng)建并初始化一個JavaBean組件,創(chuàng)建一個變量引用標(biāo)簽中的bean,接著在其它的標(biāo)簽中引用該bean。可以在一個標(biāo)簽中嵌套另一個,可以在JSP頁面中進行復(fù)雜的交互。第七頁,共105頁。聲明和使用標(biāo)簽描述標(biāo)簽開發(fā)和部署標(biāo)簽處理器自定義標(biāo)簽的描述第八頁,共105頁。1.聲明和使用標(biāo)簽

可以通過在頁面中使用下面的指令來聲明在JSP中使用標(biāo)簽庫:<%@tagliburi=”WEB-INF/testtag.tld”prefix=”tt”%>該uri屬性引用了唯一識別的標(biāo)簽庫描述符(TLD),該URI可以是直接的也可以是間接的。Prefix屬性定義了區(qū)分其它標(biāo)簽的方法。之后可以使用標(biāo)簽庫中的hello標(biāo)簽,例如:….<tt:hello/>….自定義標(biāo)簽的描述第九頁,共105頁。自定義標(biāo)簽的描述2.描述標(biāo)簽

在標(biāo)簽庫描述文件中,我們可以描述每個具體的自定義標(biāo)簽。標(biāo)簽庫描述文件必須以后綴為.tld命名。TLD文件保存在WEB-INF目錄中,你可以直接或間接的引用TLD。下面的標(biāo)簽庫指令直接引用了TLD文件:<%@tagliburi=”/WEB-INF/testtag.tld”prefix=”tt”%>下面的標(biāo)簽庫指令使用了短的邏輯名來間接引用TLD:<%@tagliburi=”/testtag”prefix=”tt”%>如果想使用邏輯名,我們需要將邏輯名/testtag映射到絕對路徑/WEB-INF/testtag.tld第十頁,共105頁。自定義標(biāo)簽的描述我們在web.xml中配置如下:<taglib><taglib-uri>/testtag</taglib-uri><taglib-location>/WEB-INF/testtag.tld</taglib-location></taglib>第十一頁,共105頁。自定義標(biāo)簽的描述3.開發(fā)和部署標(biāo)簽處理器

對于每個自定義標(biāo)簽,我們需要開發(fā)相應(yīng)的標(biāo)簽處理器(taghandler)。這是我們的重點,我們再后面的章節(jié)里會展開。部署標(biāo)簽處理器的兩種方法:將編譯過的標(biāo)簽處理器類部署到項目的WEB-INF/classes目錄下,這種方法應(yīng)用在開發(fā)自己的標(biāo)簽或標(biāo)簽處理器類數(shù)目較少的情況。將編譯過的標(biāo)簽處理器類打包成jar文件,之后部署到項目的WEB-INF/lib目錄下。這種方法應(yīng)用在需要導(dǎo)入第三方開發(fā)的標(biāo)簽或標(biāo)簽處理器類數(shù)目較多的情況。第十二頁,共105頁。7.1.2自定義標(biāo)簽種類根據(jù)對體內(nèi)容的不同行為,可以將自定義標(biāo)記分為兩種類型:處理體內(nèi)容的標(biāo)記。

對體內(nèi)容進行操作的標(biāo)記,它必須繼承接口

javax.Servlet.jsp.tagext.BodyTag。簡單標(biāo)記。

不對體內(nèi)容進行處理的標(biāo)記。它必須繼承接口javax.Servlet.jsp.tagext.Tag。

第十三頁,共105頁。處理體內(nèi)容的標(biāo)記對于體標(biāo)記的具體處理過程如下:(1)Web容器設(shè)置標(biāo)記處理器的pageContext屬性來初始化標(biāo)記處理器。(2)Web容器設(shè)置標(biāo)記處理器的parent屬性(如果標(biāo)記不被其他標(biāo)記包含,則該屬性為null)。(3)設(shè)置標(biāo)記開發(fā)定義的標(biāo)記參數(shù)(4)Web容器調(diào)用標(biāo)記處理器的doStartTag()方法。(5)調(diào)用SetBodyContent()方法。(6)調(diào)用doInitBody()方法。(7)調(diào)用doAfterBody()方法。(8)Web容器調(diào)用標(biāo)記處理器的doEndTag()方法。(9)Web容器調(diào)用標(biāo)記處理器的release()方法,釋放標(biāo)記處理執(zhí)行期間使用的資源,重置標(biāo)記處理器的屬性狀態(tài)等。第十四頁,共105頁。簡單標(biāo)記簡單標(biāo)記是不對體內(nèi)容進行處理的標(biāo)記。簡單標(biāo)記分為兩種:1)沒有體及屬性的標(biāo)簽:

<tt:simple/>2)帶有屬性的標(biāo)簽:

自定義標(biāo)簽可以含有屬性。屬性列于起端標(biāo)簽,有這樣的語法:attr=”value”。屬性值用于自定義標(biāo)簽的行為,就像方法中定義的參數(shù)一樣。

在下面的例子中,一個屬性制訂了一個請求參數(shù):name:

<tt:greetingname=”zjf”>第十五頁,共105頁。簡單標(biāo)記簡單標(biāo)記的處理過程如下:(1)Web容器設(shè)置標(biāo)記處理器的pageContext屬性來初始化標(biāo)記處理器。(2)Web容器設(shè)置標(biāo)記處理器的parent屬性(如果標(biāo)記不被其他標(biāo)記包含,則該屬性為null)。(3)設(shè)置標(biāo)記開發(fā)定義的標(biāo)記參數(shù)。(4)Web容器調(diào)用標(biāo)記處理器的doStartTag()方法。(5)Web容器調(diào)用標(biāo)記處理器的doEndTag()方法。(6)Web容器調(diào)用標(biāo)記處理器的release()方法,釋放標(biāo)記處理執(zhí)行期間使用的資源,重置標(biāo)記處理器的屬性狀態(tài)等。第十六頁,共105頁。簡單標(biāo)記定義腳本變量的標(biāo)簽

自定義標(biāo)簽可以定義在腳本中使用的變量。下面的例子展示了如何定義并使用包含從JNDIlookup返回的對象的腳本變量。這個例子包含企業(yè)bean,事務(wù)處理,數(shù)據(jù)庫,環(huán)境入口等。<t:lookupid=”tx”type=”UserTransaction”name=”java:comp/UserTransaction”/><%tx.begin();%>第十七頁,共105頁。7.1.3自定義標(biāo)簽的開發(fā)要完成一個標(biāo)簽的開發(fā),需要具有以下幾個部分:為標(biāo)簽開發(fā)一個標(biāo)簽處理器(標(biāo)簽處理類.java)在標(biāo)簽庫中聲明標(biāo)簽描述符(標(biāo)簽描述文件.tld)JSP頁面(<%@taglib%>)(可選)在web.xml文件中配置映射名稱。第十八頁,共105頁。標(biāo)簽處理器標(biāo)簽處理器是由Web容器調(diào)用的,用來處理運行的包含標(biāo)簽的JSP頁面。標(biāo)簽處理器必須實現(xiàn)Tag或BodyTag接口。這些接口可以攜帶Java對象并產(chǎn)生一個標(biāo)簽處理器。對新創(chuàng)建的處理器,你可以使用TagSupport及BodyTagSupport類作為基類,這些基類接口在javax.servlet.jsp.tagext包中。第十九頁,共105頁。標(biāo)簽處理器表13-1第二十頁,共105頁。標(biāo)簽處理器(1)對于簡單標(biāo)簽:我們必須實現(xiàn)doStartTaganddoEndTag方法,其中doStartTag必須返回SKIP_BODY這個常量,因為簡單標(biāo)簽沒有體doEndTag返回EVAL_PAGE,如果想要繼續(xù)執(zhí)行JSP頁面的其它部分,否則返回SKIP_PAGE對于標(biāo)簽的每個屬性,你必須定義屬性名和實現(xiàn)對屬性的getter/setter方法,注意這里要符合JavaBean的默認(rèn)命名規(guī)范第二十一頁,共105頁。標(biāo)簽處理器(2)對于有體的標(biāo)簽:我們必須實現(xiàn)doStartTag

和doEndTag方法,可以實現(xiàn)doAfterBody

,doInitBody

和setBodyContent方法,其中doStartTag可能返回SKIP_BODY這個常量(如果沒有體),或者EVAL_BODY_INCLUDE,EVAL_BODY_BUFFERED(如果你想使用體的內(nèi)容)doEndTag返回EVAL_PAGE,如果想要繼續(xù)執(zhí)行JSP頁面的其它部分,否則返回SKIP_PAGEdoAfterBody方法可以返回EVAL_BODY_AGAIN(如果想多次使用體),或者SKIP_BODY第二十二頁,共105頁。標(biāo)簽處理器

這些方法由JSP頁面的servlet任何時候調(diào)用。當(dāng)遇到標(biāo)簽的起始處時,JSP頁面的servlet調(diào)用方法來初始化處理器接著調(diào)用處理器的doStartTag方法,當(dāng)遇到結(jié)束點時,處理器的方法doEndTag被調(diào)用。另外的一些方法在標(biāo)簽相互通信時使用。

標(biāo)簽處理器有API接口來與jsp頁面通信。其API入口點是pagecontext(javax.servlet.jsp.PageContext)。通過API,處理器可以返回其它隱含對象(request,session,application)。

隱含對象有些屬性,它們可以通過使用[set|get]方法來調(diào)用。如果標(biāo)簽嵌套,標(biāo)簽處理器也要訪問相應(yīng)的標(biāo)簽。第二十三頁,共105頁。標(biāo)簽庫描述符

標(biāo)簽庫描述符是XML格式的文檔。TLD包含庫的所有信息及庫中的每個標(biāo)簽。TLD由Web容器使用來驗證標(biāo)簽并由JSP頁面開發(fā)工具來使用。TLD文件必須以擴展名.tld為后綴。這類文件保存在WEB-INF目錄中或它的子目錄中,當(dāng)你使用部署工具將TLD加到WAR中時,它會自動的加入到WEB-INF中。TLD文件開頭格式:<?xmlversion=”1.0”encoding=”ISO-8859-1”?><!DOCTYPEtaglibPUBLIC“-//SunMicrosystems,Inc.//DTDJSPTagLibrary1.2//EN”>第二十四頁,共105頁。標(biāo)簽庫描述符TLD的根元素是taglib,子元素列表如下:第二十五頁,共105頁。taglib子元素元素listener

標(biāo)簽庫可以指定一些類——事件監(jiān)聽類。(參照處理servlet生命周期事件)。這些監(jiān)聽類都作為listener元素列于TLD中,網(wǎng)絡(luò)容器將實例化監(jiān)聽類并通過與在WAR中定義的監(jiān)聽類類似的方法來注冊。不像WAR級的監(jiān)聽類,標(biāo)簽庫中注冊的監(jiān)聽類沒有定義順序。Listener元素的唯一子元素是listener-class,它必須包含監(jiān)聽類名的全稱。元素tag

庫中的每個標(biāo)簽都有一個給定的名稱及該標(biāo)簽的處理器來描述,標(biāo)簽創(chuàng)建的腳本變量信息,標(biāo)簽屬性信息。腳本變量信息可以直接在TLD中給出或通過標(biāo)簽的額外信息獲取。每一屬性都包含說明是否需要該屬性,它的值是否可以通過請求時表達式來決定,及其屬性類型。第二十六頁,共105頁。tag子元素下表列出了標(biāo)簽的子元素信息:第二十七頁,共105頁。簡單標(biāo)簽的開發(fā)簡單標(biāo)簽處理器必須實現(xiàn)Tag接口(或繼承TagSupport)的doStartTag及doEndTag兩個方法。方法doStartTag在開始遇到時被調(diào)用,并返回SKIP_BODY,因為簡單標(biāo)簽沒有體。方法doEndTag在標(biāo)簽結(jié)束時被調(diào)用,如果其它頁面需要使用則返回EVAL_PAGE,否則返回SKIP_PAGE。第二十八頁,共105頁。簡單標(biāo)簽的開發(fā)最簡單的標(biāo)簽:<tt:simple/>將由下面的標(biāo)簽處理器來實現(xiàn):publicSimpleTagextendsTagSupport{

publicintdoStartTag()throwsJspException{

try{

pageContext.getOut().print(“HelloWorld.”);

}catch(Exceptione){thrownewJspTagException(“SimpleTag:”+e.getMessage());}

returnSKIP_BODY;

}

publicintdoEndTag(){

returnEVAL_PAGE;

}

}TLD元素body-content:tld中沒有體的標(biāo)簽必須用body-content元素來聲明體內(nèi)容為空:

<body-content>empty</body-contnent>第二十九頁,共105頁。簡單標(biāo)簽的開發(fā)帶屬性的標(biāo)簽對于每一個標(biāo)簽屬性,你必須在標(biāo)簽處理器中定義一個屬性及get/set方法來遵循JavaBean的結(jié)構(gòu)。例如,下面的處理器處理<tt:greetingname=”Lixin”>標(biāo)簽.importjavax.servlet.jsp.tagext.*;importjavax.servlet.jsp.*;publicclassGreetingTagextendsTagSupport{privateStringname;publicvoidsetName(Stringname){=name;}publicStringgetName(){returnname;}publicintdoStartTag()throwsJspException{returnSKIP_BODY;}第三十頁,共105頁。簡單標(biāo)簽的開發(fā)

publicintdoEndTag()throwsJspException{try{//getJspWriter,sendcontenttoclientpageContext.getOut().print("Hello,"+name);}catch(java.io.IOExceptione){e.printStackTrace();}returnEVAL_PAGE;}}注意:如果屬性命名為id,標(biāo)簽處理器繼承了TagSupport類,你不需要定義該屬性及set/get方法,因為已經(jīng)由TagSupport定義了。第三十一頁,共105頁。簡單標(biāo)簽的開發(fā)TLD元素attribute對于每一個標(biāo)簽屬性,你必須指定該屬性是否必須,該標(biāo)簽的知是否可以通過表達式確定,屬性類型在元素attribute中。對于靜態(tài)類型數(shù)值通常為java.lang.String。如果元素rtexprvalue是true或者是yes,元素類型決定了返回值類型。<attribute>

<name>attr1</name>

<required>true|false|yes|no</required>

<rtexprvalue>true|false|yes|no</rtexprvalue>

<type>fully_qualified_type</type><attribute>第三十二頁,共105頁。簡單標(biāo)簽的開發(fā)

如果屬性不必須,標(biāo)簽處理器應(yīng)該指定一個默認(rèn)值標(biāo)簽元素tt:greeting聲明了一個屬性name不必須,且它的值可以有一個表達式來賦值。<tag>

<body-content>JSP</body-content>

……

<attribute>

<name>name</name>

<required>false</required>

<rtexprvalue>true</rtexprvalue>

</attribute>

……</tag>第三十三頁,共105頁。帶體的標(biāo)簽開發(fā)標(biāo)簽處理器在處理含標(biāo)簽體的標(biāo)簽時實現(xiàn)有所不同,主要取決于處理器是否需要與體交互。這里交互指的是標(biāo)簽處理器讀取或修改體的內(nèi)容。(1)標(biāo)簽處理器不與體交互(2)標(biāo)簽處理器與體交互第三十四頁,共105頁。帶體的標(biāo)簽開發(fā)

標(biāo)簽處理器不與體交互如果處理器不與體交互,標(biāo)簽處理器需要實現(xiàn)Tag接口(或繼承TagSupport)。如果標(biāo)簽的體需要計算,方法doStartTag需要返回EVAL_BODY_INCLUDE;否則,則返回SKIP_BODY.

如果標(biāo)簽處理器需要重復(fù)計算體,則該標(biāo)簽需要實現(xiàn)接口IterationTag或者繼承TagSupport。如果標(biāo)簽決定體需要再計算一次則從doStartTag和doAfterBody返回EVAL_BODY_AGAIN。第三十五頁,共105頁。帶體的標(biāo)簽開發(fā)標(biāo)簽處理器與體交互如果標(biāo)簽處理器需要與體交互,標(biāo)簽處理器必須實現(xiàn)BodyTag接口(或繼承BodyTagSupport),這樣的處理器實現(xiàn)了方法doInitBody,doAfterBody。這些方法與傳遞到標(biāo)簽處理器的體內(nèi)容交互。doInitBody方法

該方法在體內(nèi)容設(shè)置之前求值之后被調(diào)用。通常使用該方法初始化體內(nèi)容。doAfterBody方法

該方法在體內(nèi)容求值之后被調(diào)用。像方法doStartTag一樣,doAfterBody方法必須返回指示是否繼續(xù)計算體。這樣,如果體需要再計算一次,就像實現(xiàn)了迭代標(biāo)簽一樣,doAfterBody方法應(yīng)返回EVAL_BODY_BUFFERED,否則返回SKIP_BODY.第三十六頁,共105頁。帶體的標(biāo)簽開發(fā)標(biāo)簽體支持一些方法來讀寫它的內(nèi)容。標(biāo)簽處理器可以使用體內(nèi)容的getString/getReader方法從體中獲取信息,并通過writeOut方法來將體內(nèi)容寫到輸出流。寫提供writeOut方法,該方法可以通過使用標(biāo)簽處理器的方法getPreviousOut來獲取。該方法確保標(biāo)簽處理器的結(jié)果對封閉的標(biāo)簽處理器可行。下面的例子從體中讀取內(nèi)容并傳遞到一個執(zhí)行查詢的對象。由于體不需要重復(fù)計算,所以doAfterBody返回SKIP_BODY。第三十七頁,共105頁。帶體的標(biāo)簽開發(fā)

publicclassQueryTagextendBodyTagSupport

{…

publicintdoAfterBody()throwsJspTagException

{

BodyContentbc=getBodyContent();

Stringquery=bc.getString();

bc.clearBody();

try

{

Statementstm=connection.createStatement();

result=stm.executeQuery(query);

}catch(SQLExceptione){thrownewJspTagException(“QueryTag:”+e.getMessage());}

returnSKIP_BODY;

}…

}第三十八頁,共105頁。帶體的標(biāo)簽開發(fā)TLD元素body-content

對于有體的標(biāo)簽,必須用下面的方法指定體內(nèi)容的類型:

<body-content>JSP|tagdependent</body-content>

體內(nèi)容包含自定義及核心標(biāo)簽,腳本元素,HTML文本都統(tǒng)一為JSP。

注意:body-content元素的值不會影響體處理器的解釋

另外一個例子,需要對體重復(fù)計算,所以doAfterBody返回EVAL_BODY_AGAIN第三十九頁,共105頁。帶體的標(biāo)簽開發(fā)publicclassRepeatTagextendsBodyTagSupport{privateintcount;privateStringname;publicvoidsetCount(intn){count=n;}publicintgetCount(){returncount;}publicvoidsetName(Stringname){=name;System.out.println("setName:"+name);}publicStringgetName(){return;}publicintdoStartTag()throwsJspException{System.out.println("name="+name);if(name!=null)pageContext.setAttribute("name",name);if(count>0)returnEVAL_BODY_BUFFERED;elsereturnSKIP_BODY;}第四十頁,共105頁。帶體的標(biāo)簽開發(fā)publicintdoAfterBody()throwsJspException{if(count>1){count--;returnEVAL_BODY_AGAIN;}returnSKIP_BODY;}publicintdoEndTag()throwsJspException{BodyContentbc=getBodyContent();if(bc!=null){try{//writecontentofbodytoenclosingwriterbc.writeOut(bc.getEnclosingWriter());}catch(java.io.IOExceptione){e.printStackTrace();}}returnEVAL_PAGE;}publicvoidsetBodyContent(BodyContentbodycontent){this.bodyContent=bodycontent;第四十一頁,共105頁。帶體的標(biāo)簽開發(fā)在自定義標(biāo)記中引入腳本變量,需要以下幾個步驟:

(1)實現(xiàn)一個TagExtraInfo子類來定義變量。

(2)在標(biāo)記描述文件中引入TagExtraInfo子類。

(3)編寫代碼在標(biāo)記處理器本身的頁面上下文中引入變量

第四十二頁,共105頁。帶體的標(biāo)簽開發(fā)實現(xiàn)一個TagExtraInfo子類來定義變量importjavax.servlet.jsp.tagext.*;

//TagExtraInfo用于提供一些在標(biāo)簽翻譯時相關(guān)的信息。

publicclassIterateTEIextendsTagExtraInfo

{

publicIterateTEI()

{

super();

}

publicVariableInfo[]getVariableInfo(TagDatadata)

{

returnnewVariableInfo[]

{

newVariableInfo(

data.getAttributeString("name"),

data.getAttributeString("type"),

true,

VariableInfo.NESTED);

};

}

}

第四十三頁,共105頁。帶體的標(biāo)簽開發(fā)編寫代碼在標(biāo)記處理器本身的頁面上下文中引入變量VariableInfo(String

varName,StringclassName,Booleandeclare,intscope)來定義,構(gòu)造函數(shù)各參數(shù)意義如下:

varName:變量名稱,JSP中用它來訪問腳本變量。

className:類名稱,用來定義變量類型。

declare:作為一個boolean參數(shù),用來控制是否要創(chuàng)建一個新的變量。一般情況默認(rèn)值為true。

Scope:定義標(biāo)記中變量的范圍。自定義標(biāo)記中定義的變量有三種類型的范圍:NESTED、AT_begin和AT_end。如果定義的范圍是Nested,則Web容器只能在定義標(biāo)記體中獲取該變量;如果定義的范圍是AT_begin,則只有在標(biāo)記打開之后,Web容器才能獲取該變量;如果定義的范圍是AT_end,則只有在標(biāo)記關(guān)閉之后,Web容器才能獲取該變量第四十四頁,共105頁。帶體的標(biāo)簽開發(fā)tld配置

<name>iterate</name>

<tag-class>com.tfsoftware.taglib.IterateTag</tag-class>

<tei-class>com.tfsoftware.taglib.IterateTEI</tei-class>

<body-content>jsp</body-content>

<attribute>

<name>collection</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>

</attribute>

<attribute>

<name>name</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>

</attribute><attribute>

<name>type</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue></attribute>

第四十五頁,共105頁。嵌套或協(xié)作標(biāo)簽

通過共享對象實現(xiàn)標(biāo)簽的協(xié)作JSP技術(shù)支持兩種類型的對象共享。

第一種類型需要共享對象命名、存儲在pagecontext中。為了讓其它標(biāo)簽訪問,標(biāo)簽處理器使用pageContext.getAttribute(name,scope)方法。

第二種方法是由封閉的標(biāo)簽處理器創(chuàng)建的對象對內(nèi)部的標(biāo)簽處理器是可訪問的。這種形式的對象共享有個優(yōu)點,它使用了對象私有的名字空間,這樣減少了潛在的命名沖突。第四十六頁,共105頁。嵌套或協(xié)作標(biāo)簽

為訪問閉合標(biāo)簽創(chuàng)建的對象,標(biāo)簽處理器必須首先通過靜態(tài)方法TagSupport.findAncestorWithClass(from,class)或TagSupport.getParent方法獲得封閉標(biāo)簽。前一個方法應(yīng)該在特定的嵌套的標(biāo)簽處理器不能保證時使用。一旦ancestor返回,標(biāo)簽處理器就能訪問任何靜態(tài)或動態(tài)創(chuàng)建的對象。靜態(tài)創(chuàng)建的對象是父類的成員。私有對象也可以動態(tài)的創(chuàng)建。這樣的對象可以通過方法setValue存儲在標(biāo)簽處理器中,可以通過getValue方法返回。第四十七頁,共105頁。嵌套或協(xié)作標(biāo)簽一個例子是很常用的switch/case流程控制packagesample;importjavax.servlet.jsp.*;importjavax.servlet.jsp.tagext.*;importjava.util.Hashtable;importjava.io.Writer;importjava.io.IOException;publicclassSwitchTagextendsTagSupport{Stringvalue;publicSwitchTag(){super();}publicvoidsetValue(Stringvalue){this.value=value;}publicStringgetValue(){returnvalue;}publicintdoStartTag(){returnEVAL_BODY_INCLUDE;}}第四十八頁,共105頁。嵌套或協(xié)作標(biāo)簽publicclassCaseTagextendsTagSupport{Stringvalue;publicintdoStartTag()throwsJspTagException{//SwitchTagparent=(SwitchTag)findAncestorWithClass(this,SwitchTag.class);SwitchTagparent=(SwitchTag)this.getParent();try{if(parent.getValue().equals(getValue())){returnEVAL_BODY_INCLUDE;}else{returnSKIP_BODY;}}catch(NullPointerExceptione){returnSKIP_BODY;}}publicvoidsetValue(Stringvalue){this.value=value;}publicStringgetValue(){returnvalue;}}第四十九頁,共105頁。嵌套或協(xié)作標(biāo)簽使用EXISTS的子查詢時需注意:

EXISTS關(guān)鍵字前面沒有列名、常量或其他表達式。由EXISTS引出的子查詢,其選擇列表達式通常都用(*).這是因為,帶EXISTS的子查詢只是測試是否存在符合子查詢中指定條件的行,所以不必列出列名。帶EXISTS的子查詢與前面的不相關(guān)子查詢有一個明顯區(qū)別,即子查詢的查詢條件依賴于外部查詢的某個屬性值,我們稱這類查詢?yōu)橄嚓P(guān)子查詢。

求解相關(guān)子查詢的過程不能像求解不相關(guān)子查詢那樣,一次將子查詢求解出來,然后求解外部查詢,相關(guān)子查詢的內(nèi)部查詢由于與外部查詢有關(guān),因此必須反復(fù)求值,一般處理過程如下:1)首先取外部查詢中Class表的第一行記錄,根據(jù)它與內(nèi)部查詢相關(guān)的屬性值(即ClassID值)處理內(nèi)部查詢,若WHERE子句返回值為真(即內(nèi)部查詢結(jié)果非空),則取此記錄放入結(jié)果集中。2)再檢查Student表的下一行記錄。3)重復(fù)執(zhí)行步驟2,直至student表全部檢查完畢。第五十頁,共105頁。嵌套或協(xié)作標(biāo)簽綜合使用這幾個標(biāo)簽的JSP如下所示:testTag.jsp:<%@pagecontentType="text/html;charset=GBK"%><%@tagliburi="/WEB-INF/test.tld"prefix="tt"%><html><head><title>GreetingTagTest</title></head><body><tt:switchvalue="dark"><tt:casevalue="light"><P>Thisislight.</P></tt:case><tt:casevalue="Dark"><P>ThisisDark.</P></tt:case><tt:casevalue="dark"><P>Thisisdark.</P></tt:case></tt:switch></body></html>第五十一頁,共105頁。7.2JSP2.0的新特性7.2.1JSP2.0新特性概述7.2.2配置JSP屬性7.2.3JSP的表達式7.2.4自定義標(biāo)簽TagFile第五十二頁,共105頁。7.2.1JSP2.0新特性概述和JSP1.2相比,JSP2.0主要增加了如下所示的新特性。(1)直接配置JSP屬性。(2)表達式語言。(3)簡化的自定義標(biāo)簽API。(4)Tag文件語法。第五十三頁,共105頁。7.2.2配置JSP屬性JSP屬性主要包括4個方面,具體說明如下所示。是否允許使用表達式語言:可以使用<el-ignored/>元素確定,默認(rèn)值為false,即允許使用表達式語言。是否允許使用JSP腳本:可以使用<scripting-invalid/>元素確定,默認(rèn)值為false,即允許使用JSP腳本。聲明JSP頁面的編碼可以:使用<encoding/>元素確定,配置該元素后,可以代替每個頁面里page指令contentType屬性的charset部分。使用隱式包含:可以使用<include-prelude/>和<include-coda/>元素確定,可以代替在每個頁面里使用include編譯指令來包含其他頁面。第五十四頁,共105頁。在JSP中使用表達式語言的格式如下所示。${expression}1.對算術(shù)運算符或邏輯運算符的支持2.表達式語言的內(nèi)置對象3.使用自定義函數(shù)第五十五頁,共105頁。

關(guān)于ExpressionLanguage

EL變量

運算符

隱含對象

保留字7.2.3JSP的表達式第五十六頁,共105頁。

關(guān)于ExpressionLanguageJSP2.0將ExpressionLanguage(以下簡稱EL)整合進JSP標(biāo)準(zhǔn)規(guī)格。EL并非全新的語言,最早出現(xiàn)于JSTL1.0當(dāng)中,被用來簡化數(shù)據(jù)存取的相關(guān)操作。由于EL已是JSP的標(biāo)準(zhǔn),因此用戶可以選擇直接在JSP網(wǎng)頁當(dāng)中使用EL替代Java進行數(shù)據(jù)的存取操作。EL有其專屬的一套語法,包含了兩項基本要素:變量與運算符。EL內(nèi)建隱含對象(implicitvariables),以Java集合對象的型態(tài)出現(xiàn),其中儲存了網(wǎng)頁的各種信息,包含session、cookie和網(wǎng)頁傳輸過程當(dāng)中所使用的參數(shù)值。第五十七頁,共105頁。通過PAGE指令來說明是否支持EL表達式,具體舉例:<%@pagecontentType="text/html;charset=GB2312"isELIgnored="false"%>//聲明可以使用EL表達式,如果為"ture",則表示忽略${,即不能使用EL表達式。<html><head><title>EL</title></head><%!intcount=0;%><bodybgcolor="#ffffff">${count}//如何在這里用EL表達式輸入上面定義的count</body></html>第五十八頁,共105頁。EL語法

EL必須以一個金錢表示符號加上左大括號${開始,并且以右大括號}作結(jié)束。

${ELexpression} 1.對算術(shù)運算符或邏輯運算符的支持 2.表達式語言的內(nèi)置對象 3.使用自定義函數(shù)第五十九頁,共105頁。7.2.3JSP的表達式

關(guān)于ExpressionLanguage

EL變量

運算符

隱含對象

保留字第六十頁,共105頁。

EL變量

一個儲存了特定數(shù)據(jù)內(nèi)容的符號,EL可以直接對其作存取,或是結(jié)合運算符進行必要的運算之后作輸出。

EL存取變量數(shù)據(jù)的方法很簡單,例如:${username}。它的意思是取出某一范圍中名稱為username的變量。第六十一頁,共105頁。系統(tǒng)從Page,Request,Session,Application范圍查找該變量。途中找到,就直接回傳,不再繼續(xù)找下去,如全范圍內(nèi)都沒有,則回傳null。屬性范圍在EL中的名稱

Page

PageScope

Request

RequestScope

Session

SessionScope

Application

ApplicationScope第六十二頁,共105頁。7.2.3JSP的表達式

關(guān)于ExpressionLanguage

EL變量

運算符

隱含對象

保留字第六十三頁,共105頁。1.算術(shù)運算符有五個:+、-、*或$、/或div、%或mod

2.關(guān)系運算符有六個:==或eq、!=或ne、<或lt、>或gt、<=或le、>=或ge

3.邏輯運算符有三個:&&或and、||或or、!或not

4.其它運算符有三個:Empty運算符、條件運算符、()運算符

運算符第六十四頁,共105頁。

運算符運算符說明.存取beanproperty或是mapentry[]存取arrayorList元素()改變運算順序?:條件式三元運算condition?ifTrue:ifFalse+加法運算-減法運算*乘法運算/ordiv除法運算%ormod模數(shù)運算第六十五頁,共105頁。運算符說明==oreq對等運算!=orne不相等運算<orlt小于比較運算>orgt大于比較運算<=orle小于或等于比較運算>=orge大于或等于比較運算&&orand邏輯AND運算||oror邏輯OR運算!ornot布爾補碼運算empty空值運算func(args)函數(shù)調(diào)用第六十六頁,共105頁。

運算符.1運算符(.)與方括號([]).2算術(shù)運算符.3關(guān)聯(lián)運算符.4邏輯運算符.5empty運算符.6條件式三元運算符.7運算符優(yōu)先級第六十七頁,共105頁。.1運算符(.)與方括號([])無論actionelements或是隱含對象的數(shù)據(jù)內(nèi)容,均是一種集合(collection)對象,EL可以通過點運算符(.)或是方括號([])對其作存取。

當(dāng)要存取的屬性名稱中包含一些特殊字符,如.或?等并非字母或數(shù)字的符號,就一定要使用[]。如果要動態(tài)取值時,就可以用[]來做,而“.”無法做到動態(tài)取值。${param.yearValue}${param[“yearValue”]},${param[data]}第六十八頁,共105頁。.2算術(shù)運算符運算符說明+對兩個數(shù)值進行加法運算-對兩個數(shù)值進行減法運算*對兩個數(shù)值進行乘法運算/或是div對兩個數(shù)值進行除法運算%或是mod對兩個數(shù)值進行模數(shù)運算第六十九頁,共105頁。表達式A{+、-、*}B

首先如果A與B為null,則運算之后的結(jié)果,是一個long型態(tài)的0。A或B其中一個是BigDecimal,則兩者均會轉(zhuǎn)換成為BigDecimal。運算符

返回結(jié)果運算符+A.add(B)運算符-A.subtract(B)運算符*A.multiply(B)第七十頁,共105頁。A或B為Float、Double或是包含.、e或是E:的字符串(String):如果A或是B其中之一為BigInteger,兩者均會強制轉(zhuǎn)型為BigDecimal,否則轉(zhuǎn)型為Double,然后進行運算。如果A或B為BigInteger,兩者均會被強制轉(zhuǎn)換成為BigInteger,然后進行表8-4中的相關(guān)運算。運算符返回結(jié)果運算符+A.add(B)運算符-A.subtract(B)運算符*A.multiply(B)第七十一頁,共105頁。如果非上述狀況,A與B一律轉(zhuǎn)換成為Long,然后進行運算。如果運算結(jié)果產(chǎn)生例外,則為錯誤結(jié)果。

第七十二頁,共105頁。表達式A{/,div}B如果A與B為null,則運算之后回傳一個long型態(tài)的0。假若A或B為BigDecimal或是BigInteger,兩者被強制轉(zhuǎn)換成為BigDecimal并且返回A.divide(B,BigDecimal.ROUND_HALF_UP)的運算結(jié)果。如果非上述情形,A與B強制轉(zhuǎn)換成為Double然后進行運算。最后,如果運算結(jié)果產(chǎn)生例外,則為錯誤結(jié)果。第七十三頁,共105頁。表達式A{%,mod}B如果A與B為null,返回Long型態(tài)數(shù)值0。假若A或B為Float、Double或是包含.、e或是E的字符串(String),將A與B兩者強制轉(zhuǎn)換為Double之后進行運算。如果A或B為BigInteger,強制轉(zhuǎn)換為BigInteger之后,返回A.remainder(B)的運算結(jié)果。A與B如果非上述狀況則轉(zhuǎn)換為Long進行運算。最后,若運算結(jié)果發(fā)生例外,則為錯誤結(jié)果。第七十四頁,共105頁。.3關(guān)聯(lián)運算符運算符說明==andeq等于!=andne不等于<andlt小于>andgt大于<=andle小于等于>=andge大于等于第七十五頁,共105頁。表達式A{<,>,<=,>=,lt,gt,le,ge}B若是A等于B,運算符<=,le,>=或是ge返回true的結(jié)果。當(dāng)A或是B其中之一為null,返回false。假若A或B為BigDecimal,將A與B強制轉(zhuǎn)換成為BigDecimal然后返回A.compareTo(B)的運算結(jié)果。如果A或B為Float或是uble,強制轉(zhuǎn)換Double之后,進行運算。如果A或B為BigInteger,強制轉(zhuǎn)換BigInteger,然后返回A.compareTo(B)的比較結(jié)果。如果A或B為Byte、hort、Character、Integer或是Long,強制轉(zhuǎn)換成為Long然后進行運算。當(dāng)A或是B其中之一為字符串(String),強制轉(zhuǎn)換成為String之后依字母進行字符串比較。第七十六頁,共105頁。表達式A{==,!=,eq,ne}B當(dāng)A或是B其中之一為null,返回false運算結(jié)果。若A或者B為BigDecimal,兩者均會強制轉(zhuǎn)換成為BigDecimal再進行運算,對于==運算符而言,回傳一個A.equals(B)的結(jié)果,而!=運算符則返回!A.equals(B)的結(jié)果。當(dāng)A或者B為Float或是Double,兩者均會強制轉(zhuǎn)換成為Double然后進行運算。若A或者B為BigInteger,兩者均會強制轉(zhuǎn)換成為BigInteger,其中若是運算符為==,回傳A.equals(B),!=則返回!A.equals(B)的運算結(jié)果。若A或者B為Byte、Short、Character、Integer或是Long,將被強制轉(zhuǎn)換成為Long之后進行運算。若A或者B為Boolean,將被強制轉(zhuǎn)換成Boolean作運算。若A或者B為String,將被強制轉(zhuǎn)換成String作運算。第七十七頁,共105頁。.4邏輯運算符運算符說明&&或and邏輯AND運算||或or邏輯OR運算!或not布爾值補碼第七十八頁,共105頁。.5empty運算符empty被用來判斷是否指定的值為null或是空值,并且返回一個代表判斷結(jié)果的Boolean值,empty

的運用非常簡單,如下式:${emptyA}其中的A為所要判斷的值,下面為empty的運算規(guī)則:若是判斷值A(chǔ)為null,返回true的運算結(jié)果,若是A

的值為空的字符串、數(shù)組或是集合對象,也返回true

的結(jié)果,除此之外,一律返回false。第七十九頁,共105頁。.6條件式三元運算符三元運算符針對特定判斷式的運算結(jié)果,決定返回的值:${A?B:C}

A為判斷式,如果A的結(jié)果為true,返回B,否則返回C值的結(jié)果。第八十頁,共105頁。.7

運算符優(yōu)先級運算符優(yōu)先級[].()-(unary)not!empty*/div%mod+-(binary)<><=>=ltgtlege==!=eqne&&and||or?:第八十一頁,共105頁。7.2.3JSP的表達式

關(guān)于ExpressionLanguage

EL變量

運算符

隱含對象

保留字第八十二頁,共105頁。與范圍有關(guān)的隱含對象

與范圍有關(guān)的EL隱含對象包含以下四個:pageScope、requestScope、sessionScope和applicationScope;與輸入有關(guān)的隱含對象

與輸入有關(guān)的隱含對象有兩個:param和paramValues,它們是EL中比較特別的隱含對象。其他隱含對象

cookie等

隱含對象第八十三頁,共105頁。隱含對象隱含對象說明pageContext取得網(wǎng)頁運行環(huán)境的相關(guān)信息pageScope取得page范圍內(nèi)特定屬性的屬性值requestScope取得request范圍內(nèi)特定屬性的屬性值sessionScope取得session范圍內(nèi)特定屬性的屬性值applicationScope取得application范圍內(nèi)特定屬性的屬性值param取得request對象的單一參數(shù)值paramValues取得request對象的參數(shù)值header取得request對象單一標(biāo)頭值headerValues取得request對象標(biāo)頭值cookie取得request對象的cookieinitParam取得網(wǎng)頁運行環(huán)境的初始參數(shù)值第八十四頁,共105頁。EL對象與

request對象存取EL對象Request對象存取paramServletRequest.getParameter(Stringname)paramValuesServletRequest.getParameterValues(Stringname)headerHttpServletRequest.getHeader(Stringname)headerValuesHttpervletRequest.getHeaders(String)cookieHttpServletRequest.getCookies()第八十五頁,共105頁。.1pageContext.2范圍變量.3param與paramValues.4header與headerValues.5cookie

.6initParam

第八十六頁,共105頁。.1pageContextpageContext對象代表網(wǎng)頁本身,用戶可以利用這個對象輕易獲得網(wǎng)頁相關(guān)信息,其中包含用戶所傳遞的網(wǎng)頁參數(shù)、用戶名稱與主機地址等。pageContext取得其他有關(guān)用戶要求或頁面的詳細信息。

${pageContext.request.queryString}//判斷session是否為新的

${pageContext.session.id}

//取得session的ID

${pageContext.servletContext.serverInfo}

//取得主機端的服務(wù)信息第八十七頁,共105頁。.2范圍變量EL當(dāng)中4個與范圍有關(guān)的隱含對象,pageScope、requestScope、sessionScope和applicationScope,可直接用來存取屬于特定范圍內(nèi)的變量值。從對象的名稱,可以很輕易的了解這些對象的適用范圍,除此之外,它們與JSP內(nèi)建所的隱含對象基本上是相同的。EL

對象JSP

對象pageScopepageContextrequestScoperequestsessionScopesessionapplicationScopeapplication第八十八頁,共105頁。存取范圍變量在JSP網(wǎng)頁當(dāng)中取得特定范圍變量屬性,必須引用getAttribute(),并且指定所要取得的變量名稱: application.getAttribute("cname")通過EL的存取方式: ${applicationSame}第八十九頁,共105頁。.3param與paramValues

EL對象param與paramValues被設(shè)計用來提供使用request之外的一個選擇,下表列出相同效果的request方法。ELrequest${param.paraName}request.getParameter(paraName)${paramValues.paraName}request.getParameterValues(paraName)第九十頁,共105頁。Param¶mValues存取param內(nèi)容包含當(dāng)前網(wǎng)頁所有的request參數(shù),這段程序代碼取得其中名稱為yearValue的參數(shù)值。${param.yearValue}。針對取得的參數(shù)內(nèi)容,進一步對其作運算。${param.yearValue+100}param與paramValues最大的好處便是簡化了request參數(shù)數(shù)據(jù)的存取。第九十一頁,共105頁。.4header與headerValues

Header與headerValues這兩個對象可以達到

request對象取出HTTP標(biāo)頭信息的功能,語法也相對簡單許多。${header["host"]}指定不同的標(biāo)頭名稱,可直接返回相對的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論