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>
|