-
這節(jié)課使用SimpleTagSupport寫一些案例。 一,JSP2.0和1.0的標(biāo)簽庫(kù)文件的區(qū)別也就是約束頭的不同,以及相應(yīng)屬性的支持略有不同 首先新建一個(gè)包,來(lái)存放這節(jié)課的代碼。com.imooc.tag2 接下來(lái)新建一個(gè)標(biāo)簽庫(kù)的文件,imooctag2.tld 創(chuàng)建jsp2.0的標(biāo)簽庫(kù)文件,要使用jsp2.0的xml的約束頭, 2.0和1.0的標(biāo)簽庫(kù)文件的區(qū)別也就是約束頭的不同,以及相應(yīng)屬性的支持略有不同 1.0的約束頭可以在tomcat的 C:\apache-tomcat-7.0.68\webapps\examples\WEB-INF\jsp中找到,example-taglib.tld 也就是這個(gè) <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd"> 在這里我們直接使用2.0的約束頭 C:\apache-tomcat-7.0.68\webapps\examples\WEB-INF\jsp2 jsp2-example-taglib.tld 也就是這個(gè): <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> 其實(shí)我們不必關(guān)心兩者的差別,我們直接使用2.0的就可以了查看全部
-
什么是標(biāo)簽處理器?就是標(biāo)簽處理類,java文件。查看全部
-
為了開發(fā)方便,JSP規(guī)范為我們提供了SimpleTag接口的實(shí)現(xiàn)類,SimpleTagSupport那么我們?cè)诮窈蟮淖远x標(biāo)簽 開發(fā)中呢,可以直接繼承SimpleTagSupport類就可以了,這個(gè)類除了對(duì)SimpleTag接口進(jìn)行實(shí)現(xiàn)外,還增加了兩個(gè) 方法。getJspContext()和getJspBody() getJspContext()返回的是代表當(dāng)前頁(yè)面的JspContext對(duì)象, getJspBody()返回代表標(biāo)簽體的JspFragment對(duì)象。也就是標(biāo)簽體的內(nèi)容, 這節(jié)課對(duì)SimpleTag的方法進(jìn)行了大概的了解,下節(jié)課會(huì)對(duì)這些方法的使用進(jìn)行舉例說(shuō)明。查看全部
-
經(jīng)過(guò)前面的學(xué)習(xí),發(fā)現(xiàn)實(shí)現(xiàn)自定義標(biāo)簽的過(guò)程有點(diǎn)復(fù)雜,那么多的接口和方法很容易讓人頭暈,為了 更為簡(jiǎn)單快捷的開發(fā)自定義標(biāo)簽,在JSP2.0的規(guī)范中,提供了SimpleTag接口 什么是標(biāo)簽處理器?就是標(biāo)簽處理類,java文件。 來(lái)看一下SimpleTag接口提供的一些方法 在源碼中可以看到SimpleTag接口有5個(gè)方法 doTag()方法是核心方法,我們可以將所有的標(biāo)簽處理邏輯都寫在這個(gè)方法中,這個(gè)方法 會(huì)拋出一個(gè)JspException,然后我們可以通過(guò)這個(gè)異常通知WEB容器,不再執(zhí)行此標(biāo)簽后面的內(nèi)容。 setParent(JspTag),這個(gè)方法呢,由WEB容器所調(diào)用的,是將父標(biāo)簽處理器對(duì)象傳遞給標(biāo)簽處理器, getParent()是獲取當(dāng)前標(biāo)簽的父標(biāo)簽對(duì)象,比如在標(biāo)簽嵌套時(shí),可以用此方法得到當(dāng)前標(biāo)簽的父標(biāo)簽, setJSPContext(JspContext)這個(gè)方法也是由容器調(diào)用的,這個(gè)方法是將JSP頁(yè)面中的pageContext對(duì)象 傳遞給標(biāo)簽處理器對(duì)象 setJspBody(JspFragment)這個(gè)方法也由web容器調(diào)用,意思是將代表當(dāng)前標(biāo)簽體的JspFragment對(duì)象 傳遞給標(biāo)簽處理器對(duì)象,這里的參數(shù)可以理解為標(biāo)簽體的內(nèi)容 JSP引擎在處理簡(jiǎn)單標(biāo)簽的標(biāo)簽時(shí),會(huì)將標(biāo)簽體中的內(nèi)容封裝到JspFragment這個(gè)參數(shù)中,并 調(diào)用setJspBody(JspFragment)將該對(duì)象傳遞給標(biāo)簽處理器,我們就可以根據(jù)需求來(lái)控制是否輸出標(biāo)簽體 或者循環(huán)標(biāo)簽體 來(lái)看下JspFragment的源碼:它是一個(gè)抽象類,有一個(gè)invoke(Writer)這個(gè)方法。這個(gè)方法用于執(zhí)行 JspFragment對(duì)象所代表的代碼段,也就是說(shuō),我們要在標(biāo)簽體中輸出一段話,我們可以用invoke(Writer) 這個(gè)方法中的參數(shù)是一個(gè)輸出流,使用這個(gè)方法就可以將我們想要輸出的數(shù)據(jù)輸出到JSP頁(yè)面中, getJspContext()這個(gè)方法用于返回代表JSP頁(yè)面的JspContext對(duì)象,查看全部
-
jsp引擎是什么?是什么工作原理? 1、JSP引擎: 執(zhí)行JSP代碼需要在服務(wù)器上安裝JSP引擎,比較常見(jiàn)的引擎有WebLogic和Tomcat。把這些支持JSP的web服務(wù)器配置好后。就可以再客戶端通過(guò)瀏覽器來(lái)訪問(wèn)JSP頁(yè)面了. 2、JSP引擎的工作原理 當(dāng)一個(gè)JSP頁(yè)面第一次被訪問(wèn)的時(shí)候,JSP引擎將執(zhí)行以下步驟: (1)將JSP頁(yè)面翻譯成一個(gè)Servlet,這個(gè)Servlet是一個(gè)java文件,同時(shí)也是一個(gè)完整的java程序 (2)JSP引擎調(diào)用java編譯器對(duì)這個(gè)Servlet進(jìn)行編譯,得到可執(zhí)行文件class (3)JSP引擎調(diào)用java虛擬機(jī)來(lái)解釋執(zhí)行class文件,生成向客戶端發(fā)送的應(yīng)答,然后發(fā)送給客戶端 以上三個(gè)步驟僅僅在JSP頁(yè)面第一次被訪問(wèn)時(shí)才會(huì)執(zhí)行,以后的訪問(wèn)速度會(huì)因?yàn)閏lass文件已經(jīng)生成而大大提高。 當(dāng)JSP引擎街道一個(gè)客戶端的訪問(wèn)請(qǐng)求時(shí),首先判斷請(qǐng)求的JSP頁(yè)面是否比對(duì)應(yīng)的Servlet新,如果新,對(duì)應(yīng)的JSP需要重新編譯。查看全部
-
接下來(lái)在標(biāo)簽庫(kù)中注冊(cè)一個(gè)標(biāo)簽, <tag> <name>bodyTag</name> <tag-class>com.imooc.tag.BodyTagSupportDemo</tag-class> <body-content>scriptless</body-content> </tag> 然后創(chuàng)建一個(gè)頁(yè)面,使用這個(gè)注冊(cè)好的標(biāo)簽,demo6.jsp <body> <imooc:bodyTag> hello World! </imooc:bodyTag> </body> 啟動(dòng)tomcat,訪問(wèn)demo6.jsp 可以看到頁(yè)面上輸出的是修改過(guò)的值,而在控制臺(tái)上得到的是之前的值, 這樣就達(dá)到了修改標(biāo)簽體中內(nèi)容的需求查看全部
-
下面我們來(lái)寫個(gè)例子:首先我們創(chuàng)建一個(gè)標(biāo)簽處理類,BodyTagSupportDemo繼承BodyTagSupport 然后復(fù)寫doEndTag()方法 在這里由于要得到標(biāo)簽體中的內(nèi)容, 所以這里需要聲明一個(gè)BodyContent類型的變量 然后呢,再來(lái)復(fù)寫一下setBodyContent(BodyContent b)這個(gè)方法,這個(gè)方法是由容器進(jìn)行調(diào)用的 然后this.bodyContent=b; 然后我們將處理邏輯寫在doEndTag()方法中, String content=bodyContent.getString();//得到標(biāo)簽體中的內(nèi)容 這里我們將其打印一下, 接下來(lái)創(chuàng)建一個(gè)字符串String newString="idcbgp.cn"; 然后使用bodyContent來(lái)得到一個(gè)輸出流,它返回一個(gè)JspWriter 然后將這個(gè)修改后的字符串寫回到頁(yè)面中,jspWriter.write(newString); 最后return EVAL_PAGE;//EVAL_PAGE是告訴WEB容器接著執(zhí)行自定義標(biāo)簽后面的代碼,查看全部
-
這節(jié)課學(xué)習(xí)BodyTag接口和BodyTagSupport類的使用 簡(jiǎn)介BodyTag接口: BodyTag接口可以將標(biāo)簽體中的內(nèi)容修改后再輸出, BodyTag接口除了繼承自IterationTag接口的內(nèi)容之外呢,它還增加了兩個(gè)方法和兩個(gè)常量 分別是:setBodyContent(BodyContent b) doInitBody() 一個(gè)常量 EVAL_BODY_BUFFERED 而EVAL_BODY_TAG是一個(gè)已經(jīng)過(guò)時(shí)的常量,這里不再討論它 前面使用的doStartTag方法,除了返回EVAL_BODY_INCLUDE和SKIP_BODY之外呢, 它還會(huì)返回EVAL_BODY_BUFFERED 當(dāng)返回EVAL_BODY_BUFFERED時(shí),JSP引擎會(huì)創(chuàng)建一個(gè)bodyContent對(duì)象,然后依次調(diào)用 setBodyContent(BodyContent b) doInitBody() 接著執(zhí)行標(biāo)簽體中的內(nèi)容,并且 將標(biāo)簽體中的內(nèi)容通過(guò)setBodyContent(BodyContent b)方法中的BodyContent參數(shù),傳遞過(guò)來(lái), 也就是BodyContent封裝了標(biāo)簽體中的內(nèi)容,這樣就可以控制標(biāo)簽體內(nèi)容的輸出了, 那doInitBody()會(huì)在setBodyContent(BodyContent b)之后被調(diào)用 我們?cè)賮?lái)看一下BodyContent BodyContent繼承了JspWriter,根據(jù)名字,知道它是個(gè)輸出流,不同的是,它提供了一個(gè) 緩沖區(qū)來(lái)存放數(shù)據(jù),它也為我們提供了一些比較方便的方法供我們使用 比如這節(jié)課例子中所要使用到的getString()還有g(shù)etEnclosingWriter() getString()用于返回BodyContent中的一個(gè)string,也就是它會(huì)返回緩沖區(qū)中緩存的數(shù)據(jù) 而這個(gè)getEnclosingWriter()這個(gè)方法可以得到一個(gè)BodyContent所關(guān)聯(lián)的JspWriter對(duì)象查看全部
-
接下啦創(chuàng)建一個(gè)jsp頁(yè)面來(lái)使用這個(gè)標(biāo)簽 首先引入標(biāo)簽庫(kù)<%@ taglib prefix="imooc" uri="/imooc-tag" %> 在body中: <imooc:iteration items="" var=""></imooc:iteration> 這里需要個(gè)數(shù)組,為了方便起見(jiàn) 在body中直接寫java代碼: <body> <% String[] nbastar={"jordan","kobe","t-mac"}; /* 我們將nbastar存儲(chǔ)在pageContext的這個(gè)范圍中, 這樣便于我們使用EL表達(dá)式將其取出, */ pageContext.setAttribute("nbastar", nbastar); %> <imooc:iteration items="${nbastar }" var="name"> ${name } </imooc:iteration> </body> 啟動(dòng)tomcat,查看demo5.jsp 這樣的話,我們的數(shù)據(jù)就循環(huán)出來(lái)了, 這里的items這個(gè)屬性存放的是要循環(huán)迭代的數(shù)組或是集合 var這個(gè)屬性指定了迭代變量的名稱,也就是每次從集合中或是數(shù)組中呢,取出元素都會(huì)賦值給這個(gè)變量name 這樣在標(biāo)簽體中就可以引用該變量使用集合或者數(shù)組中的元素了,那么當(dāng)我們?cè)俅嗡⑿耲sp頁(yè)面的時(shí)候呢 這里只會(huì)取到第一個(gè)元素也就是下標(biāo)為0的元素,這是由于tomcat對(duì)自定義標(biāo)簽運(yùn)用了緩存的技術(shù), 后面我們會(huì)介紹一種更好的辦法來(lái)替代它, 老師這節(jié)的var變量其實(shí)沒(méi)用用到,在標(biāo)簽類中是直接寫死的name屬性,應(yīng)該用var的值, 老師應(yīng)該是故意留的一個(gè)埋點(diǎn)讓同學(xué)們?cè)囋嚨陌?,用心良苦?查看全部
-
第二步: 記下來(lái)在標(biāo)簽庫(kù)中對(duì)其進(jìn)行注冊(cè) <tag> <name>iteration</name> <tag-class>com.imooc.tag.IterationTagDemo</tag-class> <body-content>scriptless</body-content> <attribute> <name>var</name> <required>true</required> </attribute> <attribute> <name>items</name> <required>true</required> <!--允許使用表達(dá)式作為屬性值 --> <rtexprvalue>true</rtexprvalue> </attribute> </tag>查看全部
-
如何使自定義標(biāo)簽具有循環(huán)功能?jsp規(guī)范提供了IterationTag接口,從字面意思上看這是個(gè)實(shí)現(xiàn)標(biāo)簽循環(huán)的接口 我們來(lái)看一下這個(gè)接口IterationTag是繼承于Tag接口(TagSupport整個(gè)類實(shí)現(xiàn)了IterationTag整個(gè)接口) 在Tag接口的基礎(chǔ)上,它增加了EVAL_BODY_AGAIN的常量,和doAfterBody()方法,那這個(gè)方法和這個(gè)常量有什么用呢? 在執(zhí)行完自定義標(biāo)簽體后,容器將會(huì)調(diào)用doAfterBody()方法,這個(gè)方法會(huì)向容器返回常量EVAL_BODY_AGAIN或者SKIP_BODY 容器會(huì)根據(jù)返回的常量來(lái)決定是否將標(biāo)簽體的內(nèi)容再次執(zhí)行,這里來(lái)舉一個(gè)循環(huán)數(shù)組的案例, 第一步:新建標(biāo)簽的處理類,IterationTagDemo extends TagSupport 重寫doStartTag()方法和doAfterBody()方法 接下來(lái)為該類添加兩個(gè)標(biāo)簽屬性 private String var; private String[] items; 并為其提供set方法 這里還需要一個(gè)計(jì)數(shù)器,定義一個(gè)int類型的i=1; 接下來(lái)重寫doStartTag()方法。 首先判斷items數(shù)組是否為空,且items長(zhǎng)度大于0,當(dāng)條件成立,將數(shù)組中第一個(gè)元素,也就是下標(biāo)為0的元素放到 pageContext中,并且定義其key值為name if(items != null && items.length>0){ pageContext.setAttribute("name", items[0]); } 此時(shí)返回一個(gè)return EVAL_BODY_INCLUDE;也就是說(shuō)讓其執(zhí)行標(biāo)簽體。否則就SKIP_BODY 接下來(lái)重寫一下doAfterBody()方法 首先來(lái)判斷i是否小于數(shù)組的長(zhǎng)度,如果這個(gè)條件成立,我們將剩余的元素放在鍵為name的pageContext中,i++,然后 return EVAL_BODY_AGAIN;就是讓其再次執(zhí)行標(biāo)簽體查看全部
-
這里可以看到頁(yè)面并沒(méi)有正常運(yùn)行(返回http狀態(tài)碼是500) 跑出了一個(gè)錯(cuò)誤: According to TLD or attribute directive in tag file, attribute password does not accept any expressions 屬性password你能設(shè)置為任意的表達(dá)式 這是什么原因呢? 這里再回到標(biāo)簽庫(kù)描述文件中,這里要修改attribute標(biāo)簽, 在此標(biāo)簽中加上<rtexprvalue>標(biāo)簽: <attribute> <name>driver</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> 這個(gè)屬性表示可以在運(yùn)行時(shí)接收表達(dá)式的值作為屬性值,將其設(shè)置為true,下面的類似。 修改這個(gè)tld文件不需要重啟tomcat, 再次訪問(wèn)demo4.jsp可以看到頁(yè)面上顯示出了我們想要的結(jié)果 有一點(diǎn)要注意:jsp動(dòng)態(tài)元素的結(jié)果類型必須與屬性的類型相同,否則編譯器會(huì)報(bào)錯(cuò)查看全部
-
使用這種直接寫出自變量的屬性叫做靜態(tài)屬性,當(dāng)然也可以將其屬性值設(shè)置為動(dòng)態(tài)的, 這里再來(lái)創(chuàng)建一個(gè)JSP,demo4.jsp 這里使用動(dòng)態(tài)賦值的方式來(lái)創(chuàng)建屬性標(biāo)簽的值, 這里為了顯示方便,我直接將連接數(shù)據(jù)庫(kù)的代碼寫在jsp頁(yè)面中, <body> <% String driver="com.mysql.jdbc.Driver"; String url="jdbc:mysql://localhost:3306/test"; String sql="select * from students"; String username="root"; String password="root"; /*這里使用 pageContext 來(lái)將變量值設(shè)置到頁(yè)面中 */ pageContext.setAttribute("driver", driver); pageContext.setAttribute("url",url); pageContext.setAttribute("sql",sql); pageContext.setAttribute("username",username); pageContext.setAttribute("password", password); %> <!--之后使用EL表達(dá)式的形式為標(biāo)簽中的屬性賦值 --> <imooc:dbConnection password="${password}" url="${url}" driver="${driver }" sql="${sql }" username="${username }"/> </body> 我們?cè)賮?lái)訪問(wèn)一下demo4.jsp 這里可以看到頁(yè)面并沒(méi)有正常運(yùn)行(返回http狀態(tài)碼是500) 跑出了一個(gè)錯(cuò)誤: According to TLD or attribute directive in tag file, attribute password does not accept any expressions查看全部
-
下面來(lái)新建一個(gè)JSP頁(yè)面demo3.jsp 首先引用該標(biāo)簽庫(kù) <%@ taglib prefix="imooc" uri="/imooc-tag" %> 在body中: <body> <imooc:dbConnection password="root" url="jdbc:mysql://localhost:3306/test" driver="com.mysql.jdbc.Driver" sql="select * from students" username="root"/> </body> 然后啟動(dòng)tomcat,訪問(wèn)這個(gè)jsp 這樣呢,在頁(yè)面中呢,就可以看到用這種方式將數(shù)據(jù)庫(kù)中的數(shù)據(jù)取了出來(lái), 使用這種直接寫出自變量的屬性叫做靜態(tài)屬性,當(dāng)然也可以將其屬性值設(shè)置為動(dòng)態(tài)的查看全部
-
由于這里要連接數(shù)據(jù)庫(kù),所以在項(xiàng)目中要將mysql的驅(qū)動(dòng)拷入進(jìn)去, 第二步:在標(biāo)簽類描述文件中注冊(cè)該標(biāo)簽,并配置屬性標(biāo)簽 然后修改一下標(biāo)簽庫(kù)描述文件imooctag.tld 這里新加入一個(gè)tag <tag> <name>dbConnection</name> <tag-class>com.imooc.tag.DBConnectionTag</tag-class> <body-content>empty</body-content> <attribute> <name>driver</name> <required>true</required> </attribute> <attribute> <name>url</name> <required>true</required> </attribute> <attribute> <name>username</name> <required>true</required> </attribute> <attribute> <name>password</name> <required>true</required> </attribute> <attribute> <name>sql</name> <required>true</required> </attribute> </tag> 其中: <attribute> <name>driver</name> <required>true</required> </attribute> 的name的值是標(biāo)簽處理類中的成員變量driver required意思是這個(gè)屬性是必須的,要設(shè)置為true 然后其他的屬性的設(shè)置方法都和它相似。 這樣我們的標(biāo)簽就注冊(cè)成功了查看全部
舉報(bào)
0/150
提交
取消