Scripting Variable是用於自訂標籤與JSP頁面之間溝通的變數,您可能會需要取出標籤運算之後的值,以便在接下來的JSP頁面中進行運算,例如取出某個標籤運算後的值,設定為另一個標籤運算的屬性值。
有幾種方式可以用於設定Scripting
Variable,主要的概念都是在JSP頁面轉譯為Servlet時,透過一個中介者讓Container知道那些變數該轉譯為Scripting
Variable,以便JSP頁面與自訂標籤可以共用這個變數,這個類別可以是一個類別、也可以是一個web.xml中的描述。
設定Scripting Variable的一個方法,就是將之設定給pageContext,然後再告訴Container,設定pageContext的方法如下:
pageContext.setAttribute("varname", vardata);
來看一個例子,首先我們撰寫下面這個類別:
package onlyfun.caterpillar; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; public class DecodeTag extends TagSupport { private String code;
public void setCode(String code) { this.code = code; }
public int doStartTag() throws JspException { code = code + "-decoded"; pageContext.setAttribute("decoded", code); return SKIP_BODY; } }
這個類別模擬解碼的過程,decoded是用來作為Scripting Variable的變數名稱,接下來必須告知容器這個資訊,作法之一,就是透過TagExtraInfo類別與VariableInfo類別,直接來看如何撰寫:
package onlyfun.caterpillar; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; public class TagExtraDemo extends TagExtraInfo { public VariableInfo[] getVariableInfo(TagData data) { VariableInfo info = new VariableInfo("decoded", "String", true, VariableInfo.AT_END); return new VariableInfo[] {info}; } }
getVariableInfo()方法傳回VariableInfo的陣列值,陣列值的內容就是Scripting
Variable的相關資訊,在VariableInfo中的建構中傳入四個參數:Scripting Variable名稱、Scripting
Variable型態、之前有無宣告過、作用範圍。
第三個參數若設定為true,表示之前有宣告過,直接使用宣告過的變數,如果為false,則會生成新的實例;第四個參數為Scripting Variable在JSP頁面中可以作用的範圍,分為三種:
- VariableInfo.AT_BEGIN:作用範圍從標籤開始至JSP頁面結束。
- VariableInfo.AT_END:作用範圍從標籤結束至JSP頁面結束。
- VariableInfo.AT_NESTED:作用範圍從標籤開始至標籤結束。
接下來在tld檔中告訴容器有關於自訂標籤及TagExtraInfo類別的資訊:
... <tag> <description>Decode</description> <name>decode</name> <tag-class>onlyfun.caterpillar.DecodeTag</tag-class> <tei-class>onlyfun.caterpillar.TagExtraDemo</tei-class> <body-content>empty</body-content> <attribute> <name>code</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> ...
其中<tei-class>標籤即用來告訴容器有關於TagExtraInfo類別的資訊,容器將JSP頁面轉譯為Servlet時就會用到這個資訊,可以這麼測試:
<%@taglib prefix="caterpillar" uri="http://caterpillar.onlyfun.net/"%> <html> <body> 解碼前:${ param.code } <br> <caterpillar:decode code="${ param.code }"/>
解碼後:${ decoded } </body> </html>
上面這個方法的好處是使用一個類別集中管理標籤的Scripting
Variable,缺點則是若要修改變數,則必須修改TagExtraInfo類別後重新編譯等;另一個方法則只要在tld檔案中直接設定即可,不用透過
TagExtraInfo類別,設定的例子如下:
... <tag> <description>Decode</description> <name>decode</name> <tag-class>onlyfun.caterpillar.DecodeTag</tag-class> <body-content>empty</body-content> <attribute> <name>code</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name-given>decoded</name-given> <variable-class>String</variable-class> <declare>true</declare> <scope>AT_END</scope> </attribute> </tag> ...
這次不需要透過<tei-class>的指定了,所使用的是<name-given>、<
variable-class>、<declare>與<scope>四個標籤,其意義與VariableInfo建構時
的四個參數相同。
使用固定的變數名稱,則使用自訂標籤的人員必須事先知道Scripting Variable的名稱,才可以在JSP頁面中呼叫使用它,也可以讓使用自訂標籤的人員自行決定名稱,方法是使用<name-from- attribute>,例如:
... <tag> <description>Decode</description> <name>decode</name> <tag-class>onlyfun.caterpillar.DecodeTag</tag-class> <body-content>empty</body-content> <attribute> <name>code</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>varname</name> <required>true</required> </attribute> <attribute> <name-from-attribute>varname</name-from-attribute> <variable-class>String</variable-class> <declare>true</declare> <scope>AT_END</scope> </attribute> </tag> ...
然後自訂標籤處理類別必須作一些修改,使其能夠接收varname屬性:
package onlyfun.caterpillar;
import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*;
public class DecodeTag extends TagSupport { private String varname; private String code;
public void setVarname(String varname) { this.varname = varname; }
public void setCode(String code) { this.code = code; }
public int doStartTag() throws JspException? { code = code + "-decoded"; pageContext.setAttribute(varname, code);
return SKIP_BODY; } }
接下來就可以在JSP頁面中這麼使用:
<%@taglib prefix="caterpillar" uri="http://caterpillar.onlyfun.net/"%> <html> <body> 解碼前:${ param.code } <br>
<caterpillar:decode varname="keyword" code="${ param.code }"/>
解碼後:${ keyword } </body> </html>
如果您透過繼承SimpleTagSupport類別來實作自訂標籤,則在設定Scripting Variable時,可以簡單的使用JspContext的setAttribute()方法來設定,而不需要額外的設定tld檔案,例如:
package onlyfun.caterpillar; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; public class SimpleDecodeTag extends SimpleTagSupport { private String code; public void setCode(String code) { this.code = code; } public void doTag() throws JspException { code = code + "-decoded"; getJspContext().setAttribute("decoded", _code); } }
您可以使用下面這個JSP網頁進行測試:
<%@taglib prefix="caterpillar" uri="http://caterpillar.onlyfun.net/"%> <html> <body> 解碼前:${ param.code } <br> <caterpillar:decode code="${ param.code }"/> 解碼後:${ decoded } </body> </html>
|