From Gossip@caterpillar

JSP/Servlet: 簡介 Tag Library

 

 


為了實現視圖邏輯分離的模式,您可以使用JavaBean以及Expression Language,使用EL可以讓您很簡單的取得JSP中設定的一些屬性,而使用JavaBean則可以讓您將一些資料儲存在JavaBean中,並作一 些適當的邏輯運算,然而為了完成一些網頁格式的處理以及一些視圖的限定存取,您還是不免在JSP網頁中使用scriptlet。

您可以將一些網頁格式處理或是視圖限定存取之類的,使用JSP標籤庫(Tag Library)來處理,您將格式處理或視圖限定存取的部份,撰寫在一個標籤處理類別(Tag Handler class)中,然而定義好標籤庫定義檔案(.tld),接下來您就可以在JSP網頁中使用自訂的標籤庫來撰寫網頁,例如像< caterpillar:copyright/>這樣的標籤來顯示一段版權宣告。

先實地演練一篇如何撰寫JSP標籤庫並應用,首先撰寫一個標籤處理類別:

  • CopyRightTag.java
package onlyfun.caterpillar;

import java.io.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class CopyRightTag extends TagSupport {
public int doStartTag() {
try {
JspWriter out = pageContext.getOut();
out.println("<table border=1>");
out.println("\t<td bgcolor=yellow>");
out.println(
"\t\t<b>caterpillar.onlyfun.net(c)2004<b>");
out.println("\t</td>");
out.println("</table>");
}
catch(Exception e) {}

return SKIP_BODY;
}
}

為了要能編譯上面這個類別,您需要將jsp-api.jar加至CLASSPATH中,在Tomcat的話jsp-api.jar是放在common/lib目錄下。

如上所示,為了實作一個標籤處理類別,您可以繼承TagSupport(javax.servlet.jsp.tagext 套件下)類別, TagSupport類別實作了一些介面,其中重要的是Tag與IterationTag,這都將是以後要說明的重點,這邊您先要瞭解的就是,繼承 TagSupport的類別並不對標籤本體作處理,您所能決定的只是要不要顯示本體,例如:
<caterpillar:copyright>
    額外的版權宣告文字。。。。。
<caterpillar:copyright/>
 
如果您繼承了TagSupport類別,您所能決定的,就是要不要顯示標籤<caterpillar: copyright>與<caterpillar:copyright/>之間的文字,而沒有辦法對這段文字作任何的處理,如果您要對 本體文字作處理,可以繼承BodyTagSupport類別。

回到上面所撰寫的標籤處理類別,它從pageContext中取得了JspWriter物件,然而輸出了一個表格與版權文字,最後我們傳回了 Tag.SKIP_BODY常數變數,這是doStartTag()合法的傳回值,表示不顯示標籤之間的文字本體,另一個合法傳回值是 Tag.EVAL_BODY_INCLUDE,這將會顯示標籤之間的文字本體。

為了要編譯這個類別,您必須在您的CLASSPATH中加入jsp-api.jar的路徑,編譯完成之後,要將之放置在WEB-INF/classes/ 之下,接下來可以撰寫標籤庫定義.tld檔了,如下:

  • tagdemo.tld
<?xml version="1.0" encoding="UTF-8" ?> 

<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
web-jsptaglibrary_2_0.xsd"
version="2.0">

<description>Tag Demo</description>
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>TagDemo</short-name>
<uri>/TagDemo</uri>

<tag>
<description>CopyRight Text</description>
<name>copyright</name>
<tag-class>
onlyfun.caterpillar.CopyRightTag
</tag-class>
<body-content>empty</body-content>
</tag>

</taglib>

這是個XML檔,每個標籤都已經表明了自身的意義,其中<name>所設定的,就是待會將在JSP網頁中使用的標籤名,<body- content>的內容設定為empty,表示這個標籤不處理本體文字,除了empty之外,<body- content>的內容還可以是JSP、scriptless、tagdependent, 設定為JSP的話,表示本體如果是JSP的元素,將會先執行完,再傳給標籤庫作處理,Scriptless表示本體內容不可以是scriptlet,但可 以是EL或動作元素等其它JSP元素, tagdependent的話表示不作任何處理,直接將本體內容傳給標籤庫,有標籤庫自行處理本體內容。

假設這個檔案儲存為tagdemo.tld,並放置在WEB-INF/tlds/下,為了方便管理,再於web.xml中添加一些uri與tld檔的對應:

  • web.xml
...
<jsp-config>
<taglib>
<taglib-uri>
http://caterpillar.onlyfun.net/
</taglib-uri>
<taglib-location>
/WEB-INF/tlds/tagdemo.tld
</taglib-location>
</taglib>
</jsp-config>
...

上面這些步驟與定義EL自訂函式的過程其實是類似的,接下來在JSP網頁中使用自訂JSP標籤的方式也是類似,使用taglib指令元素來指定所使用的自訂標籤,如下:
  • tagTest.jsp
<%@taglib prefix="caterpillar" 
uri="http://www.caterpillar.onlyfun.net/"%>
<html>
<body>
這個網頁是有版權的OOOXXXX。。。。。。<p>
<caterpillar:copyright/>
</body>
</html>

然後就可以執行JSP網頁了,您可以看到,只要一個標籤,就可以完成一些網頁格式的設定,結果如下:
<html>
<body>
    這個網頁是有版權的OOOXXXX。。。。。。<p>
<table border=1>
     <td bgcolor=yellow>
         <b>caterpillar.onlyfun.net(c)2004<b>
     </td>
</table>
</body>
</html>