Java TagSupport中的Id

Java TagSupport中的Id,java,jsp,servlets,Java,Jsp,Servlets,在创建JSP标记时,我有时会创建一个属性“id”,以设置所创建元素的元素id。对于该id,我还创建了一个setter。现在我发现TagSupport已经有了一个带有专用setter的属性“id”,我覆盖了该方法 到目前为止,它对我的应用程序并没有负面影响,但有人能告诉我这个id是用来做什么的,以及在覆盖它时会出现什么问题吗?一个有趣的问题 如果查看TagSupport的源代码,您会发现原始的setId/getId方法只是getter和setter: protected String id; p

在创建JSP标记时,我有时会创建一个属性“id”,以设置所创建元素的元素id。对于该id,我还创建了一个setter。现在我发现TagSupport已经有了一个带有专用setter的属性“id”,我覆盖了该方法

到目前为止,它对我的应用程序并没有负面影响,但有人能告诉我这个id是用来做什么的,以及在覆盖它时会出现什么问题吗?

一个有趣的问题

如果查看TagSupport的源代码,您会发现原始的setId/getId方法只是getter和setter:

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;
}
此方法来自标记接口:

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方法(而不是字段访问)来访问这个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:

我在tomcat 7下对此进行了测试,Closole输出为:

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
你可以得到:

id = dog
id = dog
id = cat
id = cat
因此,如果您的代码依赖于这些ID。重写此setId/getId方法可能会导致某些容器出现问题,并且很难找到bug

所以不要跳过这个setId/getId方法

还有一件事。不要使用clasic标记,这是旧的API。使用SimpleTagSupport

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
id = dog
id = null
id = cat
id = null 
id = dog
id = dog
id = cat
id = cat