[创建JSP标签时,有时会创建属性“ id”来设置所创建元素的元素ID。为此,我还创建了一个setter。现在,我发现TagSupport已经具有专用设置程序的属性“ id”,并且我重写了该方法。
直到现在它对我的应用程序都没有负面影响,但是任何人都可以告诉我该ID的含义以及在覆盖它时会导致什么问题吗?
有趣的问题
如果查看TagSupport的源代码,您会发现原始的setId / getId方法只是获取器和设置器:
protected String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
在该类中,只有一种方法可以直接调用id字段:
public void release() {
parent = null;
id = null;
if( values != null ) {
values.clear();
}
values = null;
}
此方法来自Tag界面:
public interface Tag extends JspTag {
...
/**
* Called on a Tag handler to release state.
* The page compiler guarantees that JSP page implementation
* objects will invoke this method on all tag handlers,
* but there may be multiple invocations on doStartTag and doEndTag in between.
*/
void release();
...
}
如果我们假设其他内部类使用get / set方法(而不是字段acces)来访问此id属性,那么只需担心一个地方(此发布方法)。
JSP规范指出:“ JSP容器可以将经典的标记处理程序实例重用于多个在同一页面或不同页面中出现相应的自定义操作页面,但前提是所有事件均使用相同的属性集。“
[我认为,可能导致某些问题的唯一情况是,当您有两个带有ID的标签,一个没有ID且没有标签的容器重用实例。
测试用例:
标签类别:
public class TestTag extends TagSupport {
protected String id;
static int count = 0;
int instanceNuber=0;
public TestTag() {
super();
System.out.println("TestTag.TestTag() - new Instance");
instanceNuber = ++count;
}
@Override
public int doStartTag() throws JspException {
JspWriter out = pageContext.getOut();
try {
out.print("id = " + getIdWrapper());
} catch (IOException e) {
}
return (SKIP_BODY);
}
public String getIdWrapper() {
return getId();
}
@Override
public String getId() {
System.out.println("Instance " + instanceNuber + " of TestTag.getId() = " + id);
return id;
}
@Override
public void setId(String id) {
System.out.println("Instance " + instanceNuber + " of TestTag.setId(" + id + ")");
this.id = id;
}
}
JSP:
<my:test id="dog"/>
<br/>
<my:test/>
<br/>
<my:test id="cat"/>
<br/>
<my:test/>
<br/>
打印:
id = dog
id = null
id = cat
id = null
我在tomcat 7下进行了测试,并且clonsole输出为:
TestTag.TestTag() - new Instance <- new instance for first occurance of tag with id
Instance 1 of TestTag.setId(dog)
Instance 1 of TestTag.getId() = dog
TestTag.TestTag() - new Instance <- new instance for first occurance of tag without id
Instance 2 of TestTag.getId() = null
Instance 1 of TestTag.setId(cat) <- reuse of instance 1
Instance 1 of TestTag.getId() = cat
Instance 2 of TestTag.getId() = null <- reuse of instance 2
回答您的问题
看起来只有所有相同的属性都使用相同的属性时,tomcat才会重用经典的标记处理程序实例。无论属性集的外观如何,其他容器都可以为同一页面上的所有标签重用实例。
因此,在Tomcat下,对您的应用程序没有负面影响,因为您有2个实例(在我的情况下)。一个用于具有ID的标签,另一个用于具有相同ID但没有ID的标签(标签的一个实例用于给定的一组属性)。因此,不必担心页面上的某些标签会从以前使用的实例继承一些“旧” ID。
但是在其他容器上而不是输出上:
id = dog
id = null
id = cat
id = null
您可以获得:
id = dog
id = dog
id = cat
id = cat
因此,如果您的代码取决于这些ID。重写此setId / getId方法可能会在某些容器上引起问题,并且很难发现错误。
所以不要覆盖此setId / getId方法。
还有一件事。不要使用经典标签,这是旧的API。使用SimpleTagSupport。