自定义标签的功能扩展
自定义标签的其中一个作用就是替换jsp中的scriptlet代码,提高该程序段的重用性。为此肯定需要更多样化的功能以满足不同需求。通常有三种方法来拓展自定义标签的功能:
1.创建标签属性.
2.建立代码段变量.
3.使用标签额外信息类(TEI).
1.创建自定义标签的属性
功能需求
在上个显示当前时间的例子中格式是固定在处理类中的,可不可以在jsp中通过标签来设置呢,这里就需要一个该标签的属性用来设置时间格式。
实践
修改标签处理程序类,将原来的固定字符串改为变量,并为此变量设置set方法。这里的set方法类似于javaBean规范中的,方便与tld文件的属性关联。
public class TagProcess extends TagSupport {
private String timeFormat;
@Override
public int doEndTag() throws JspException {
String time = new SimpleDateFormat(timeFormat).format(new Date());
try {
pageContext.getOut().print(time);
} catch (IOException e) {
e.printStackTrace();
}
return EVAL_PAGE;
}
public void setTimeFormat(String timeFormat) {
this.timeFormat = timeFormat;
}
}
修改TLD文件中的tag标签,加入属性:
<tag>
<name>nowTime</name>
<tag-class>javaBeansInJSP.TagProcess</tag-class>
<body-content>empty</body-content>
<attribute>
<name>timeFormat</name>
<rtexprvalue>false</rtexprvalue>
<type>java.lang.String</type>
</attribute>
</tag>
去JSP页面中设置该属性值:
<body>
now let’s look at the time :<timem:nowTime timeFormat = "YY-MM-DD hh:mm:ss"/>
</body>
显示如下:
原理
在tld文件的tag标签里面加入属性标签<attribute>
标签,设置其名称,类型等等。并在标签处理类中设置该属性,属性名称和标签里的一样,添加set方法。在jsp文件里标签中为属性赋值就在标签处理程序中使用。
attribute标签的一些子属性设置,required设置为true的话意思是你必须要为该属性设置值,rtexprvalue设置为true意思是该属性值可以设置成scriptlet的计算结果也可以为该属性设置任何类型的对象。
2.建立代码段变量
需求
有时候我们需要标签内的属性或者说变量能够直接在jsp中使用,为了实现这种交互呢,有两种方式可以实现,一种是TLD文件中声明,另一种是使用TEI类。
可以看一个例子,我想在jsp页面中显示一个数组的所有元素,可以用如下方法。这个例子只做演示。
这是一个标签处理类(对应于ADC标签库里的createADC标签),在类里面有个数组,我直接写死,然后设置到pageContext里面如下:
public class CreateADCs extends TagSupport{
private List<String> adcs = Arrays.asList("麦林炮手","奥巴马","薇恩");
@Override
public int doEndTag(){
pageContext.setAttribute("ADCS", adcs);
return EVAL_BODY_INCLUDE;
}
}
再在jsp页面中,创建标签执行添加操作之后,再用scriptlet代码从pageContext获取,之所以这么做是标签内的变量没法与jsp直接交互数据。
<body>
<ADC:createADC/>
<%
List<String> ADCS=(List<String>)pageContext.getAttribute("ADCS");
%>
<br>
<h1>There are the adcs</h1>
<%
for (String adc:ADCS) {
out.print(adc+" ");
}%>
</body>
显示结果如下:
在TLD文件中创建标签变量
为了解决以上的麻烦,我们使用标签变量。
标签处理类不变,仍旧往ADCS里面放数据,在TLD里面声明这么一个ADCS变量。它会自动得到pageContext的attribute为值为自己初始化。tld文件改变如下:
<tag>
<name>createADC</name>
<tag-class>javaBeansInJSP.CreateADCs</tag-class>
<body-content>empty</body-content>
<variable>
<name-given>ADCS</name-given>
<variable-class>java.util.List<String></variable-class>
<declare>true</declare>
<scope>AT_END</scope>
</variable>
</tag>
在jsp文件中直接访问这个变量ADCS即可:
<body>
<ADC:createADC/>
<br>
<h1>There are the adcs</h1>
<%
for (String adc:ADCS) {
out.print(adc+" ");
}
%>
</body>
细节
atrribute属性 | 描述 |
---|---|
description* | 该变量的相关信息 |
name-given / name-from-attribute | 变量名 |
variable-class? | 变量类型 |
declare? | 是否是新的变量。默认值为true,表示新建该变量 |
scope? | 该变量的生效范围。AT_BEGIN|NESTED|AT_END 分别表示在标签起始、只在标签内、标签结束 开始生效。 |
用TEI类来创建该变量
另外一种方式来创建该变量就是用tag标签里的tei类来实现。
首先建立一个这样的TEI类,继承variableInfo类,实现其方法:
public class CreateSkillTEI extends TagExtraInfo {
@Override
public VariableInfo[] getVariableInfo(TagData data) {
// TODO Auto-generated method stub
VariableInfo vi = new VariableInfo(data.getAttributeString("adcsName"),
data.getAttributeString("adcsType"), true, VariableInfo.AT_END);
VariableInfo[] tagVariables = new VariableInfo[1];
tagVariables[0]=vi;
return tagVariables;
}
}
上边代码中,返回的是变量的数组,可以实现创建多个变量返回给jsp,传入值为该tei类所对属标签的对应标签类的数据,通过该tagdata可以获取标签类里面的属性,用来设置该变量。variableInfo的四个参数和tld创建标签变量时一样。我们获取了两个属性name和type,就需要在标签类里面设置:
public class CreateSkill extends TagSupport {
private List<String> skillList= Arrays.asList("圣枪洗礼","毁灭射击","终极时刻");
private String adcsName="defaultName";
private String adcsType="java.util.List<String>";
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
pageContext.setAttribute(adcsName, skillList);
return EVAL_BODY_INCLUDE;
}
public void setAdcsName(String adcsName) {
this.adcsName = adcsName;
}
public void setAdcsType(String adcsType) {
this.adcsType = adcsType;
}
}
如上设置了两个属性,并且向JSP页面设置了变量值。只需要再在tld里面配置属性,配置tei-class就好了:
<tag>
<name>createSkill</name>
<tag-class>javaBeansInJSP.CreateSkill</tag-class>
<tei-class>javaBeansInJSP.CreateSkillTEI</tei-class>
<body-content>JSP</body-content>
<attribute>
<name>adcsName</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.String</type>
</attribute>
<attribute>
<name>adcsType</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.String</type>
</attribute>
</tag>
在jsp中使用:
<h1>There are the skills</h1>
<ADC:createSkill adcsName ="someSkills" adcsType="java.util.List<String>" />
<%
out.print(someSkills);
%>
上边代码在eclipse里面报错,不认为someSkills是一个变量,事实上可以运行。而且可以在里面读到变量值:
总结:
自定义标签通过添加属性获得了更丰富的表达和灵活的处理,但是当与jsp页面交互的时候需要用pageContext来传递对象,同时jsp又是需要为jsp页面创建标签对象,这时候用tei为标签加入属性name,type,并作用到创建的标签对象上,就可以直接在自定义标签里面用该标签的属性来创建JSP里面直接用的变量了。