JSP/Servlet: Scripting Variable

Scripting Variable是用于自订标签与JSP页面之间沟通的变数,您可能会需要取出标签运算之后的值,以便在接下来的JSP页面中进行运算,例如取出某个标签运算后的值,设定为另一个标签运算的属性值。

有几种方式可以用于设定Scripting Variable,主要的概念都是在JSP页面转译为Servlet时,透过一个中介者让Container知道那些变数该转译为Scripting Variable,以便JSP页面与自订标签可以共用这个变数,这个类别可以是一个类别、也可以是一个web.xml中的描述。

设定Scripting Variable的一个方法,就是将之设定给pageContext,然后再告诉Container,设定pageContext的方法如下:
pageContext.setAttribute("varname", vardata);


来看一个例子,首先我们撰写下面这个类别:

* DecodeTag.java

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类别,直接来看如何撰写:

* TagExtraDemo.java

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类别的资讯:

* decode.tld

...
<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时就会用到这个资讯,可以这么测试:

* test.jsp

<%@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类别,设定的例子如下:

* decode.tld

...
<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>,例如:

* decode.tld

...
<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属性:

* DecodeTag.java

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页面中这么使用:

* test.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档案,例如:

* SimpleDecodeTag.java

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网页进行测试:

* test.jsp

<%@taglib prefix="caterpillar"
uri="http://caterpillar.onlyfun.net/"%>
<html>
<body>

解码前:${ param.code } <br>

<caterpillar:decode code="${ param.code }"/>

解码后:${ decoded }

</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值