標(biāo)準(zhǔn)的JSP 標(biāo)記可以調(diào)用JavaBeans組件或者執(zhí)行客戶的請求,這大大降低了JSP開發(fā)的復(fù)雜度和維護(hù)量。
JSP技術(shù)也允許你自定義taglib,其實(shí)換句話說,taglib可以看成是對JSP標(biāo)記的一種擴(kuò)展,正如xml是對
html的一種擴(kuò)展一樣。taglib通常定義在tag標(biāo)簽庫中,這種標(biāo)簽庫存放著你自己定義的tag標(biāo)簽。
簡而言之,如果使用taglib,那么你可以設(shè)計(jì)自己的JSP標(biāo)記!
一般來說,自定義tag標(biāo)簽主要用于操作隱藏對象、處理html提交表單、訪問數(shù)據(jù)庫或其它企業(yè)級的服務(wù),
諸如郵件和目錄操作等等。自定義tag標(biāo)簽的使用者一般都是那些對java編程語言非常精通,而且對數(shù)據(jù)
訪問和企業(yè)級服務(wù)訪問都非常熟悉的程序員,對于HTML設(shè)計(jì)者來說,使得他可以不去關(guān)注那些較復(fù)雜的商
業(yè)邏輯,而將精力放在網(wǎng)頁設(shè)計(jì)上。同時(shí),它也將庫開發(fā)者和庫使用者進(jìn)行合理分工,自定義tag標(biāo)簽將
那些重復(fù)工作進(jìn)行封裝,從而大大提高了生產(chǎn)力,而且可以使得tag庫可用于不同的項(xiàng)目中,完美地體現(xiàn)
了軟件復(fù)用的思想。
在這篇文章中,我們主要討論:
· 什么是自定義tag標(biāo)簽?
· 怎么使用tag標(biāo)簽?
o 聲明要使用的tag庫
o 找到與之對應(yīng)的tag處理類
o tag標(biāo)簽的類型
· 自定義tag標(biāo)簽
o tag處理類
o tag庫描述
o tag標(biāo)簽示例
o 帶屬性的tag
o 帶body的tag
o 定義了腳本變量的tag
o 具有協(xié)作關(guān)系的tag
· 自定義tag標(biāo)簽
o 一個迭代tag的例子
o 一個模板tag庫
o tag處理類到底是怎樣被調(diào)用的?
什么是自定義的tag?
一個自定義的tag標(biāo)簽是用戶定義的一種JSP標(biāo)記。當(dāng)一個含有自定義的tag標(biāo)簽的JSP頁面被jsp引擎編譯
成servlet時(shí),tag標(biāo)簽被轉(zhuǎn)化成了對一個稱為tag處理類的對象進(jìn)行的操作。于是當(dāng)JSP頁面被jsp引擎轉(zhuǎn)
化為servlet后,實(shí)際上tag標(biāo)簽被轉(zhuǎn)化成為了對tag處理類的操作。
自定義tag標(biāo)簽有很多特色,諸如:
· 可以在JSP頁面中自定義tag標(biāo)簽的屬性
· 訪問JSP頁面中的所有對象
· 可以動態(tài)地修改頁面輸出
· 彼此這間可以相互通信。你可以先創(chuàng)建一個JavaBeans組件,然后在一個tag中調(diào)用此JavaBeans組件,
同時(shí)可以在另一個tag中調(diào)用它。
· tag允許相互嵌套,可以在一個JSP頁面中完成一些復(fù)雜的交互。
使用tag標(biāo)簽
本節(jié)主要描述怎樣在JSP頁面中使用tag標(biāo)簽,以及tag標(biāo)簽的不同類型。
要使用tag標(biāo)簽,JSP程序員必須做2件事:
· 聲明此tag標(biāo)簽的tag庫
· 實(shí)現(xiàn)此tag標(biāo)簽
聲明tag標(biāo)簽所在的tag庫
如果要使用tag標(biāo)簽,則應(yīng)用JSP的taglib指示符來指定其tag庫(注意:taglib要在在使用此tag標(biāo)簽之前聲明)
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
uri屬性定義了唯一的標(biāo)簽庫描述(以下簡稱TLD),它可以是直接是tld文件名或一個獨(dú)一無二的名字。
prefix是用來區(qū)別其它TLD中和本TLD中有重名的tag的一種手段。
TLD必須以.tld作為擴(kuò)展名,并且存放在當(dāng)前應(yīng)用的WEB-INF目錄或其子目錄下。你可以通過它的文件名
直接引用它,也可以通過別的方式間接地引用它。
以下taglib指示符直接引用一個TLD:
<%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %>
以下的taglib指示符通過一個邏輯名稱間接地引用一個TLD:
<%@ taglib uri=”/tutorial-template” prefix=”tt” %>
如果是間接引用TLD的話,那你必須還要在web.xml中定義此邏輯名稱與tld文件之間的映射,具體做法
是在web.xml中加入一個名為taglib的元素:
<taglib>
<taglib-uri>/tutorial-template</taglib-uri>
<taglib-location>
/WEB-INF/tutorial-template.tld
</taglib-location>
</taglib>
實(shí)現(xiàn)此tag標(biāo)簽
為了實(shí)現(xiàn)tag標(biāo)簽,你有2種方法來存放tag處理類。一、讓tag處理類以.class的方式存放于當(dāng)前應(yīng)用
的WEB-INF/class子目錄下,二、如果tag處理類是以JAR包的形式存在的話,那可以放在當(dāng)前應(yīng)用的
WEB-INF/lib目錄下,如果tag處理類要在多個應(yīng)用中共享,那么它就應(yīng)放在jsp服務(wù)器上的common/lib
目錄下,對于tomcat來說,就是tomcat/common/lib目錄下。
tag標(biāo)簽類型
自定義的tag標(biāo)簽遵循XML語法。它有一個開始標(biāo)記和一個結(jié)束標(biāo)記,有的還有body(即文本節(jié)點(diǎn)):
<tt:tag>
body
</tt:tag>
一個不帶body的tag標(biāo)簽如下:
<tt:tag />
簡單的tag標(biāo)簽
一個沒有body和屬性的tag標(biāo)簽如下:
<tt:simple />
帶屬性的tag標(biāo)簽
自定義標(biāo)簽可以有自己的屬性。屬性一般在開始標(biāo)記中定義,語法為 attr=”value”。屬性的作用相當(dāng)
于自定義標(biāo)簽的一個參數(shù),它影響著tag處理類的行為。你可以在TLD中詳細(xì)定義它。
你可以用一個String常量給一個屬性賦值,也可以通過表達(dá)式給它賦值,如<%= ...%>。以struts為例,
它的logic:present標(biāo)簽就是用的String常量來給屬性賦值:
<loglic:present parameter = “Clear”>
而另一個標(biāo)簽logic:iterate是用表達(dá)式來給屬性賦值:
<logci:iterate collection=”<%= bookDB.getBooks() %>”
id=”book” type=”database.BookDetails”>
帶body的tag標(biāo)簽
一個自定義標(biāo)簽可以包含其它自定義標(biāo)簽、腳本變量、HTML標(biāo)記或其它內(nèi)容。
在下述例子中,此JSP頁面使用了struts的logic:present標(biāo)簽,如果些標(biāo)簽定義了parameter=”Clear”的
屬性,則將清除購物車的內(nèi)容,然后打印出一條信息:
<logic:present parameter=”Clear”>
<% cart.clear(); %>
<font color=”#ff0000” size=”+2”><strong>
你選擇了清除購物車!
</strong></font>
</logic:present>
到底是用屬性還是用body來傳遞信息?
如上所述,我們既可以通過屬性,也可以通過body來傳遞信息。但一般來說,比較簡單的類型,如字符串
或簡單表達(dá)式最好采用屬性來傳遞信息。
定義腳本變量的tag標(biāo)簽
所謂腳本變量,是指JSP中可以調(diào)用的變量或?qū)ο蟆K捎蓆ag標(biāo)簽產(chǎn)生。以下示例闡述了一個tag標(biāo)簽定義
了一個名為tx的由JNDI所定義的事務(wù)處理對象。腳本變量可以是ejb對象、事務(wù)、數(shù)據(jù)庫連接等等:
<tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” />
<% tx.begin(); %>
...
具有協(xié)作關(guān)系的tag標(biāo)簽
自定義tag標(biāo)簽之間可以通過共享對象來實(shí)現(xiàn)協(xié)作。在下述例子中,標(biāo)簽tag1創(chuàng)建了一個名為obj1的對象,
在標(biāo)簽tag2仍可以重復(fù)使用obj。
<tt:tag1 attr1=”obj1” value1=”value” />
<tt:tag2 attr1=”obj1” />
在以下這個例子當(dāng)中,如果外層的tag標(biāo)簽創(chuàng)建了一個對象,那么其內(nèi)層的所有tag標(biāo)簽都可以使用這個對象。
由于這樣產(chǎn)生的對象沒有一個指定的名字,那么就可以將少重名的沖突。這個例子闡述了一系列協(xié)作的嵌套對象。
<tt:outerTag>
<tt:innerTag />
</tt:outerTag>
Tag處理類
Tag處理類必須實(shí)現(xiàn)Tag接口或BodyTag接口,不過現(xiàn)在一般都流行從TagSupport或BodyTagSupport類中繼承,
這些類或接口都可以在javax.servlet.jsp.tagext包中找到。
當(dāng)JSP引擎看到自己的JSP頁面中包含有tag標(biāo)簽時(shí),它會調(diào)用doStartTag方法來處理tag標(biāo)簽的開頭,
調(diào)用doEndTag方法來處理tag標(biāo)簽的結(jié)束。
下表說明不同類型的tag所需要不同的處理過程:
Tag處理類的方法
Tag標(biāo)簽類型
所調(diào)用的方法
基本標(biāo)簽
doStartTag, doEndTag, release
帶屬性的標(biāo)簽
doStartTag, doEndTag, set/getAttribute1...N, release
帶內(nèi)容的標(biāo)簽
doStartTag, doEndTag, release
帶內(nèi)容的標(biāo)簽,且
內(nèi)容重復(fù)循環(huán)
doStartTag, doAfterBody, doEndTag, release
帶內(nèi)容的標(biāo)簽,且內(nèi)容與JSP交互
doStartTag, doEndTag, release, doInitBody, doAfterBody, release
一個tag處理類可以通過javax.servlet.jsp.PageContext來與JSP交互,通過javax.servlet.jsp.PageContext類,
tag處理類可以訪問JSP中的request、session和application對像。
如果tag標(biāo)簽是互相嵌套的,那內(nèi)層的tag處理類可以通過它的parent屬性來訪問上層的tag處理類。
一般情況都將所有的tag處理類打成了JAR的包,以便于發(fā)布。
Tag庫描述(簡稱TLD)
Tag庫是用xml語言描述的,TLD包括了tag庫中所有tag標(biāo)簽的描述,它一般用來被jsp服務(wù)器用來校驗(yàn)tag的語法
正確性,或者被jsp開發(fā)者用來開發(fā)新的標(biāo)簽。
TLD的文件擴(kuò)展名必須為.tld,而且必須放在當(dāng)前WEB應(yīng)用的WEB-INF目錄或其子目錄中。
一個TLD的內(nèi)容的開頭必須遵守標(biāo)準(zhǔn)的XML開頭,用于描述DTD和xml的版本,例如:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "
TLD必須以<taglib>來作為它的根元素,<taglib>的子元素如下表:
<taglib>的子元素
Element
Description
tlib-version
Tag庫的版本
jsp-version
Tag庫所需要的jsp的版本
short-name
助記符,tag的一個別名(可選)
uri
用于確定一個唯一的tag庫
display-name
被可視化工具(諸如Jbuilder)用來顯示的名稱(可選)
small-icon
被可視化工具(諸如Jbuilder)用來顯示的小圖標(biāo)(可選)
large-icon
被可視化工具(諸如Jbuilder)用來顯示的大圖標(biāo)(可選)
description
對tag庫的描述(可選)
listener
參見下面listener元素
tag
參見下面tag 元素
Listener元素
一個tag庫可能定義一些類做為它的事件偵聽類,這些類在TLD中被稱為listener 元素,
jsp服務(wù)器將會實(shí)例化這些偵聽類,并且注冊它們。Listener元素中有一個叫l(wèi)istener-class的子元素,
這個元素的值必須是該偵聽類的完整類名。
Tag元素
每個tag元素在tag庫中都要指出它的名字、類名、腳本變量、tag的屬性。其中腳本變量的值可以
直接在TLD中定義或通過tag附加信息的類來取得。每個屬性描述了這個屬性是否可以省略,它的值
是否可以通過<%= …%>這樣的JSP語法來獲得,以及屬性的類型。
每一個tag在TLD中對應(yīng)一個tag元素,下表是tag元素的子元素:
Tag元素的子元素
元素名稱
描述
name
獨(dú)一無二的元素名
tag-class
Tag標(biāo)簽對應(yīng)的tag處理類
tei-class
javax.servlet.jsp.tagext.TagExtraInfo的子類,用于表達(dá)腳本變量(可選)
body-content
Tag標(biāo)簽body的類型
display-name
被可視化工具(諸如Jbuilder)用來顯示的名稱(可選)
small-icon
被可視化工具(諸如Jbuilder)用來顯示的小圖標(biāo)(可選)
large-icon
被可視化工具(諸如Jbuilder)用來顯示的大圖標(biāo)(可選)
description
此tag標(biāo)簽的描述
variable
提供腳本變量的信息(同tei-class)(可選)
attribute
Tag標(biāo)簽的屬性名
以下章節(jié)介紹對于不同類型的tag,如何具體地實(shí)現(xiàn)它們。
簡單的tag
tag處理類
簡單的tag處理類必須實(shí)現(xiàn)Tag接口的doStartTag和doEndTag方法。當(dāng)jsp引擎碰到tag標(biāo)簽的開頭時(shí),
doStartTag被調(diào)用,因?yàn)楹唵蔚膖ag沒有body,所以此方法將返回 SKIP_BODY。當(dāng)jsp引擎碰到tag標(biāo)簽的
結(jié)尾時(shí),doEndTag被調(diào)用,如果余下的頁面還要被計(jì)算,那它將返回EVAL_PAGE,否則將會返回SKIP_PAGE。
以下是例子:對于標(biāo)簽 <tt:simple /> ,它的tag處理類實(shí)現(xiàn)如下:
public SimpleTag extends TagSupport
{
public int doStartTag() throws JspException
{
try{
pageContext.getOut().print(“Hello.”);
}catch(Exception e){
throw new JspTagException(“SimpleTag: “ + e.getMessage());
}
return SKIP_BODY;
}
public int doEndTag()
{
return EVAL_PAGE;
}
}
注意:如果tag標(biāo)簽沒有內(nèi)容的話,那必須定義body-content元素為空,例如
<body-content>empty</body-content>
帶屬性的tag標(biāo)簽
tag處理類
對于tag標(biāo)簽的每個屬性,你必須依照J(rèn)avaBeans規(guī)范來定義其屬性,以及get和set方法。以struts的
logic:present 標(biāo)簽為例,
<logic:present parameter=”Clear”>
與此相應(yīng),此tag處理類應(yīng)有如下方法和定義:
protected String parameter = null;
public String getParameter()
{
return this.parameter;
}
public void setParameter(String parameter)
{
this.parameter = parameter;
}
注意:如果你的屬性名為id,而且你的tag處理類是從TagSupport類繼承的,那你就不需要定義它的屬性
和set和get方法,因?yàn)樗麄冊缫言赥agSupport被定義過了。
posted on 2007-08-14 23:50
jadmin 閱讀(107)
評論(0) 編輯 收藏