簡介
使用JavaServer Pages來產生動態的網頁,大體可以分為兩種方式,一是 Scripting & Bean,這是利用 script 來撰寫程式,並在其中嵌入 JavaBean 來處理比較複雜的部份,另一種方式則是使用Tag Library,以 Tag 來取代一般常用的函式及運算,甚至用來連結資料庫(JDBC)、處理郵件(JavaMail)以及連結訊息伺服器(JMS)等。 在這部分的練習中,我們將會建立您的第一組Jsp Tag Library,這組Tag Library包含最簡單的功能–它將在您的JSP頁面中顯示一組字串。在整個練習過程中我們首先為您介紹一個Tag Library的基本結構與運作流程,接下來我們將為這個Tag撰寫描述子並將其部署到我們的Web Server,最後則是測試此Tag是否正常地運作。
可執行JSP頁面之WebServer:
本練習中我們使用Apache Tomcat 4.1.12
首先,我們所建立的每一個Tag都必須實作javax.servlet.jsp.tagext.Tag這個Interface
Tag大約可分為兩大類型:Body Tag或Tag(有時稱Simple Tag),在本文中,我們將以Simple Tag作為練習。
下圖為一個Tag標籤的生命週期:
當使用者請求一張JSP頁面時,Container開始解析這張JSP頁面,而當解析至一個Tag時,Container將執行以下的動作:
- 使用此Tag的setPageContext()方法,設定目前的PageContext,以便於往後使用。
- 使用setParent()方法來設定Container所解析到包含此Tag的外層Tag標籤(假如沒有則傳入null)。
- 設定所有定義於此標籤內之屬性值。
- 呼叫doStartTag(),此方法將回傳EVAL_BODY_INCLUDE或SKIP_BODY整數值。假如回傳值為EVAL_BODY_INCLUDE時,兩Tag(Body Tag)標籤中的內容將繼續被解析,假如回傳值為SKIP_BODY,則Container將會略過此Tag之內容部分。
- 呼叫doEndTag(),這個方法將回傳EVAL_PAGE或SKIP_PAGE整數值,回傳值為EVAL_PAGE時,Container在結束此標籤後,將繼續解析剩餘的JSP內容;而當回傳值為SKIP_PAGE時,Container在解析完此標籤後,將停止解析剩餘的JSP內容。
- 最後,則會呼叫release()方法,您可以使用此方法來釋放此標籤所使用過的任何資源
下圖則為Tag Library的例外處理機制:
當呼叫doStartTag()或doEndTag()方法時出現錯誤,Container將發出一個JspTagException。
由於這是我們的第一個標籤,我們將一步一步實作Tag介面中的每一個方法,而暫時先不使用一些J2EE中所提供較為便利的類別檔(例如:TagSupport或BodyTagSupport)。
首先,在您所建立的Web Project目錄中(例如 “C:\Tomcat4.1.12\webapps\taglib”)底下的 ”WEB-INF/classes” 新增一 'HelloWorldTag.java' 的檔案,其說明如下:
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
/**
* A simple Tag that displays a Hello World message.
*/
public class HelloWorldTag implements Tag {
|
首先,我們要使此類別檔實作javax.servlet.jsp.tagext.Tag介面。
private PageContext pageContext;
private Tag parent;
|
加入此兩變數以儲存目前之PageContext以及外層的Tag標籤。
/**
* Constructor
*/
public HelloWorldTag() {
super();
}
|
實作此標籤之建構子。
/**
* Method called at start of Tag
* @return either a EVAL_BODY_INCLUDE or a SKIP_BODY
*/
public int doStartTag() throws javax.servlet.jsp.JspTagException {
return SKIP_BODY;
}
|
接下來,我們實作doStartTag()方法,並回傳SKIP_BODY代表我們將不考慮此標籤中所包含之JSP內容。
/**
* Method Called at end of Tag
* @return either EVAL_PAGE or SKIP_PAGE
*/
public int doEndTag() throws javax.servlet.jsp.JspTagException {
try {
pageContext.getOut().write("Hello World!");
}
catch(java.io.IOException e) {
throw new JspTagException("IO Error: " + e.getMessage());
}
return EVAL_PAGE;
}
|
以上的內容表示,我們使用PageContext將 "Hello World!" 此字串寫回client端中,也就是我們的JSP Page並且注意到,我們所回傳的值為EVAL_PAGE,表示Container將繼續完成剩餘的JSP內容,假如我們想讓此JSP在執行完此標籤後即停止顯示,則可將回傳值替換為SKIP_PAGE。
/**
* Method called to releases all resources
*/
public void release() {}
|
由於此標籤結構簡單,所以我們並不需在此作任何釋放資源的動作。
/** Method used by the JSP container to set the current PageContext
* @param pageContext, the current PageContext
*/
public void setPageContext(final javax.servlet.jsp.PageContext pageContext) {
this.pageContext=pageContext;
}
/** Method used by the JSP container to set the parent of the Tag
* @param parent, the parent Tag
*/
public void setParent(final javax.servlet.jsp.tagext.Tag parent) {
this.parent=parent;
}
|
以上兩方法由JSP Container所呼叫,用來設置此標籤之PageContext以及外層標籤。
** Method for retrieving the parent
* @return the parent
*/
public javax.servlet.jsp.tagext.Tag getParent() {
return parent;
}
}
|
最後,我們也要實作getParent()此方法。
接著請編譯您的程式碼。
當您的第一個標籤編譯完成後,我們需要一個描述子(descriptor)來描述這個標籤,以便讓您的JSP Page能夠認得這個標籤:
<taglib>
<taglib-uri>mytags</taglib-uri>
<taglib-location>/WEB-INF/taglib.tld</taglib-location>
</taglib>
|
為了測試您的標籤,請在您的Web Project目錄下加入如下的JSP Page
<%@ taglib uri="mytags" prefix="mt" %>
<HTML>
<HEAD>
<TITLE>Hello World!</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<HR>
<mt:helloWorld/>
<HR>
</BODY>
</HTML>
|
最後,開啟您的Web Server,並在瀏覽器中鍵入http://localhost/taglib/helloWorld.jsp
看到以上的畫面時,代表您已經完成了第一個Tag了。
|