,,
(1.江南大學(xué)信息工程學(xué)院,江蘇 無(wú)錫 214122;2.中國(guó)船舶科學(xué)研究中心,江蘇 無(wú)錫 214082)
眾所周知,軟件開發(fā)人員和頁(yè)面設(shè)計(jì)人員往往因?yàn)橐恍┲睾系臉I(yè)務(wù)邏輯功能而交織在一起不能獨(dú)立工作,以致于頁(yè)面設(shè)計(jì)人員不能把精力集中在使用標(biāo)簽創(chuàng)建網(wǎng)站上,而軟件開發(fā)人員也不能將精力完全集中在底層功能的實(shí)現(xiàn)上[1];此外JSP和Servlet 作為J2EE 平臺(tái)中生成動(dòng)態(tài)WEB的技術(shù),雖能產(chǎn)生相同的效果,但JSP在內(nèi)容中嵌入了邏輯,從而降低了JSP頁(yè)面的可讀性、可維護(hù)性和可復(fù)用性,而Servlet在邏輯中嵌入了內(nèi)容,以至于其邏輯處理混亂,可讀性差,同時(shí)也給表示內(nèi)容的維護(hù)帶來(lái)了不利。雖然JavaBean的引入很好地解決了JSP和Servlet面臨的兩難處境,使J2EE平臺(tái)Web組件的開發(fā)很好地實(shí)現(xiàn)了內(nèi)容和表示、業(yè)務(wù)邏輯的分離,但JavaBean只是可復(fù)用組件,無(wú)法獲取運(yùn)行環(huán)境信息?;谝陨蠁?wèn)題,引入自定義標(biāo)簽是一個(gè)很好的解決途徑,可以使Web組件開發(fā)中的表示和業(yè)務(wù)邏輯代碼相分離,大大增強(qiáng)了代碼的可讀性、可維護(hù)性和可復(fù)用性。
當(dāng)一個(gè)含有自定義標(biāo)簽的JSP頁(yè)面被編譯成servlet時(shí),實(shí)際上標(biāo)簽被轉(zhuǎn)化成了對(duì)標(biāo)簽處理類的操作,即JSP引擎會(huì)根據(jù)頁(yè)面指令<%@ taglib>去訪問(wèn)TLD的相關(guān)處理程序信息,調(diào)用它的構(gòu)造器方法,啟動(dòng)標(biāo)簽處理程類,讀取其屬性和相應(yīng)值。如果是第一次使用,則對(duì)每個(gè)屬性都調(diào)用set方法。然后JSP服務(wù)器調(diào)用處理程序的doStartTag(),再調(diào)用doEndTag()方法。最后在頁(yè)面結(jié)尾調(diào)用release ()方法,清理占用的所有資源。
因此定制標(biāo)簽的首要組件就是要寫一個(gè)實(shí)現(xiàn)標(biāo)簽功能的JAVA類,即標(biāo)簽處理器。它必須實(shí)現(xiàn)Tag接口或BodyTag接口[2],但通常的做法是繼承TagSupport或BodyTagSupport類,具體使用什么接口或者抽象類取決于開發(fā)人員定義的方法所預(yù)期的生命周期。
其次寫一個(gè).tld格式的標(biāo)簽庫(kù)描述器組件。它定義了標(biāo)簽庫(kù)的名稱、版本信息、描述信息各標(biāo)簽的名稱、對(duì)應(yīng)的標(biāo)簽處理器,標(biāo)簽的屬性等內(nèi)容。
另外,還需要一個(gè)部署標(biāo)簽庫(kù)的xml文檔,是用來(lái)注冊(cè)描述標(biāo)簽庫(kù)相關(guān)信息的文檔,一般在WEB服務(wù)器啟動(dòng)時(shí)被加載到內(nèi)存中。WEB服務(wù)器依此來(lái)調(diào)度資源響應(yīng)用戶的請(qǐng)求。
其通常實(shí)現(xiàn)的接口有:javax.servlet.jsp.tagext.Tag以及其擴(kuò)展接口IterationTag和 BodyTag。為了簡(jiǎn)化用戶開發(fā)通常在javax.servlet.jsp.tagext包中還提供了等一些支持類,方便標(biāo)簽處理器實(shí)現(xiàn)眾多的方法。
通常標(biāo)簽的信息存儲(chǔ)在一個(gè)用XML編寫的TLD文檔中。因?yàn)闃?biāo)簽庫(kù)是一些標(biāo)簽的集合,它們之間有一定聯(lián)系,加之標(biāo)簽處理器的方法有很多是容器回調(diào)方法,編寫完標(biāo)簽后,只有向WEB容器提供關(guān)于標(biāo)簽的信息,才能在用戶引用時(shí),WEB容器知道怎樣調(diào)用相應(yīng)的方法來(lái)處理客戶的請(qǐng)求[4]。因此將其相應(yīng)的信息放在一個(gè)說(shuō)明文件里有利于引用時(shí)的操作。
由于標(biāo)簽庫(kù)使用TLD文件描述,因而部署標(biāo)簽庫(kù)實(shí)際上就是要發(fā)布TLD文件,通常把它放在WebContent下的WEB-INFO文件夾里。在web.xml文件中提供標(biāo)簽庫(kù)描述文件的路徑[4]。
本文結(jié)合的項(xiàng)目是ShipDB_Test系統(tǒng)的子系統(tǒng),船舶性能試驗(yàn)數(shù)據(jù)庫(kù)系統(tǒng),其具體需求見圖1。
船舶試驗(yàn)數(shù)字化平臺(tái)是一個(gè)基于SOA(Service-Oriented Architecture)架構(gòu)的試驗(yàn)數(shù)據(jù)服務(wù)平臺(tái)系統(tǒng),它實(shí)現(xiàn)了多個(gè)實(shí)驗(yàn)室的試驗(yàn)系統(tǒng)的無(wú)縫集成。由于該服務(wù)平臺(tái)包含多個(gè)子系統(tǒng),因此在項(xiàng)目的集成過(guò)程中,項(xiàng)目的登錄成了需要解決的焦點(diǎn),既不能影響其它系統(tǒng)的登錄,還得在登錄后能實(shí)現(xiàn)原本的權(quán)限控制以及功能實(shí)現(xiàn)。因此,在平臺(tái)的開發(fā)過(guò)程中定義了一個(gè)標(biāo)簽庫(kù),實(shí)現(xiàn)的主要功能有:實(shí)現(xiàn)不同用戶登錄及操作的權(quán)限控制,與其他系統(tǒng)集成后的單點(diǎn)登錄(集成后,標(biāo)簽中需要修改相應(yīng)的參數(shù))等。在此僅給出選擇不同的語(yǔ)言登錄標(biāo)簽的實(shí)現(xiàn)過(guò)程。
圖1 船舶性能試驗(yàn)數(shù)據(jù)庫(kù)系統(tǒng)結(jié)構(gòu)
相應(yīng)標(biāo)簽處理程序的部分源碼如下:
public class EnglishTag extends TagSupport {
/** Instance Variables、Property
* Public Methods */
public int doStartTag() throws JspException {HttpServletRequest request=(HttpServletRequest) pageContext.getRequest(); getAttribute(org.apache.struts.Globals.MODULE_KEY);
HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
String path = new String();
path = request.getServletPath();
String html = “”;
html=“
StringBuffer results = new StringBuffer(html);
/* jspwriter是一個(gè)隱含對(duì)象,用于向jsp網(wǎng)頁(yè)輸出內(nèi)容 */
JspWriter writer = pageContext.getOut();
try {
writer.print(results.toString());
} catch (IOException e) {
throw new JspException (messages.getMessage(“l(fā)inkItem.io”, e.toString())); return (EVAL_BODY_INCLUDE);}
public int doEndTag() throws JspException {
JspWriter writer = pageContext.getOut();
try {
writer.print(“”);
} catch (IOException e) {
throw new JspException
(messages.getMessage(“l(fā)ink.io”, e.toString()));}
return (EVAL_PAGE);}
public void release() {
super.release();//釋放占用的所有資源
action = “Show”; }
}
選擇其他語(yǔ)言登錄的標(biāo)簽處理器類和以上是很相似的,其不同點(diǎn)是 “l(fā)anguage=eng&path”中value值的變化。
/*標(biāo)頭信息 */
/*標(biāo)簽庫(kù)定義信息 */
/*標(biāo)簽庫(kù)信息*/
/*標(biāo)簽屬性集*/
將rmc.tld文件放在WebContent下的WEB-INFO目錄下,接下來(lái)就可以在JSP文件中導(dǎo)入定制的標(biāo)簽庫(kù)和定制的標(biāo)簽了,操作的語(yǔ)法如下:
/*導(dǎo)入標(biāo)簽庫(kù)*/
<%@ taglib uri=“/WEB-INF/rmc.tld” prefix=“rmc” %>
/*引用標(biāo)簽*/
本文的創(chuàng)新之處在于以簡(jiǎn)單明了的自定義標(biāo)簽來(lái)實(shí)現(xiàn)原來(lái)項(xiàng)目中繁雜冗余的源碼功能。例如,在SOA開發(fā)中,多個(gè)系統(tǒng)集成而又不影響各個(gè)獨(dú)立系統(tǒng)的登錄的做法可以利用單點(diǎn)登錄的解決方案,即所有應(yīng)用系統(tǒng)的“統(tǒng)一登錄”,用戶一次登錄即可訪問(wèn)其有權(quán)訪問(wèn)的系統(tǒng)資源,提高了企業(yè)的工作效率。通常的做法就是利用專門的工具來(lái)實(shí)現(xiàn)。而在本系統(tǒng)中采用標(biāo)簽來(lái)實(shí)現(xiàn)如此繁瑣的功能,不僅使項(xiàng)目變得簡(jiǎn)單易維護(hù),也使得Web組件開發(fā)中的表示和業(yè)務(wù)邏輯相分離[5],提高了開發(fā)效率。
[1] David M geary.JSP高級(jí)開發(fā)與應(yīng)用[M].賀民,譯.北京:科學(xué)出版社,2006.
[2] 戎 偉,張 雙.精通Struts-java流行服務(wù)器、框架、工具及整合的應(yīng)用[M].北京:人民郵電出版社,2006.
[3] 張新曼.精通JSP—WEB開發(fā)技術(shù)與典型應(yīng)用[M].北京:人民郵電出版社,2006.
[4] 邱 哲,王俊標(biāo),馬 斗.Struts Web設(shè)計(jì)與開發(fā)大全[M].北京:清華大學(xué)出版社,2006.
[5] 梁愛虎.基于服務(wù)總線的Struts+EJB+Web Service整合應(yīng)用開發(fā)[M].北京:電子工業(yè)出版社,2006.