火星文 技术研习社

Noname Cat, Keep Thinking
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[转] JSP/Servlet: TagSupport 類別

Posted on 2007-01-14 20:42  剑廿三  阅读(497)  评论(0编辑  收藏  举报

http://caterpillar.onlyfun.net/Gossip/JSPServlet/TagSupport.htm

From Gossip@caterpillar

JSP/Servlet: TagSupport 類別

如果在自訂標籤庫時,並不需要對標籤本體作處理,則您可以繼承TagSupport類別,TagSupport類別實作了TagIterationTag介面,IterationTag介面則是Tag介面的子介面,TagSupport類別替您預先實作了這兩個介面中的方法,在繼承TagSupport之後,您視需要來改寫當中的一些方法(這是 Default Adapter模式)。

Tag介面中與標籤處相關的方法主要有:doStartTag()、doEndTag()。其中doStartTag()方法是遇到標籤開始時會呼叫的方法,其合法的回傳值是EVAL_BODY_INCLUDE與SKIP_BODY,前者表示將顯示標籤間的本體文字,後者表示不顯示標籤間的本體文字;doEndTag()方法是在遇到標籤結束時呼叫的方法,其合法的回傳值是EVAL_PAGE與SKIP_PAGE,傳回前者表示處理完標籤後繼承執行以下JSP網頁,傳回後者則表示不處理接下來的JSP網頁。

IterationTag介面繼承Tag介面,在標籤處理上增加了doAfterBody(),這個方法是在顯示完標籤間文字本體之後呼叫的,其合法的回傳值有EVAL_BODY_AGAIN與SKIP_BODY,如果傳回前者,則會再顯示一次標籤間的文字本體,傳回後者則繼承執行標籤處理的下一步。

TagSupport類別實作了Tag與IterationTag介面,其預設的回傳值是:doStartTag()回傳 SKIP_BODY、doAfterBodyTag()回傳SKIP_BODY、doEndTag()回傳EVAL_PAGE。所以在繼承 TagSupport之後,如果沒有改寫任何的方法,則在標籤處理上執行的順序是:

doStartTag() -> 不顯示本體文字 -> doEndTag() -> 執行接下來的JSP網頁

如果您改寫了doStartTag(),則您必須指定回傳值,如果指定了EVAL_BODY_INCLUDE,則預設會照以下的順序執行:

doStartTag() -> 顯示本體文字 -> doAfterBodyTag()->doEndTag()->執行接下來的JSP網頁

簡單的說,如果您繼承了TagSupport並改寫了其中的一些方法,則您必須指定方法合法的回傳值,如果不改寫,則會有其預設的回傳值,/以下作個流程整理:
TagSupport流程

如果您在處理標籤時,引用了一些資源,例如檔案I/O或是資料庫連結,則您可以改寫release()方法,這個方法會在doEndTag()之後執行,您可以在處理完標籤之後用它來釋放先前所使用到的資源。

下面這個程式簡單的示範如何使用自訂標籤來對網頁內容作一些保護:
  • GuardTag.java
package onlyfun.caterpillar; 

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

public class GuardTag extends TagSupport {
public int doStartTag() throws JspException {
String valid =
pageContext.getRequest().getParameter("valid");

// 如果flag設定為key,就顯示本體文字內容
if(valid.equals("valid_user")) {
return EVAL_BODY_INCLUDE;
}

return SKIP_BODY;
}
}

同樣的,程式編譯完之後,放置在WEB-INF/classes/之下,然後編譯.tld檔案,如下:
  • guardtag.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>Cuard BodyText</description>
<name>guard</name>
<tag-class>onlyfun.caterpillar.GuardTag</tag-class>
<body-content>JSP</body-content>
</tag>

</taglib>

在<body-content>中設定的是JSP,這表示如果本體中包括JSP網頁的內容,將會被編譯執行,接下來您可以在web.xml中定義uri與.tld的名稱對應關係,方法與前一個主題相同,這邊就不重複說明了,然後撰寫一個測試的JSP網頁:
  • test.jsp
<%@taglib prefix="caterpillar" 
uri="http://caterpillar.onlyfun.net/"%>
<html>
<body>
這個網頁包括受保護的內容OOOXXXX。。。。。。<p>
<caterpillar:guard>
${ param.user }, 您好,幸運密碼是 oooxxx !
</caterpillar:guard>
</body>
</html>

為了要能看到幸運密碼,您必須在請求中包括guard參數,假設請求是:
http://localhost:8080/myjsp/test.jsp?valid=valid_user&user=Justin

這樣就可以看到幸運密碼了:
<html>
<body>
    這個網頁包括受包護的內容OOOXXXX。。。。。。<p>
   
        Justin, 您好,幸運密碼是: oooxxx !
   
</body>
</html>
 
這是部份防護網頁內容的一個簡單例子,您還可以在doEndTag()中使用SKIP_PAGE來防護標籤以下的整個網頁,這使得您不用在JSP網頁中包括防護的判斷邏輯。