java - TagSupport 中的 ID

标签 java jsp servlets

在创建 JSP 标签时,我有时会创建一个属性“id”来设置所创建元素的元素 ID。对于那个 id,我还创建了一个 setter。现在我发现 TagSupport 已经有一个属性“id”和它的专用 setter ,我重写了那个方法。

到目前为止,它对我的​​应用程序没有负面影响,但有人能告诉我该 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;
}

该方法来自Tag接口(interface):

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 属性,那么只有一个地方需要担心(这个 release 方法)。

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

您可以获得:

id = dog
id = dog
id = cat
id = cat

因此,如果您的代码依赖于这些 ID。覆盖此 setId/getId 方法可能会导致某些容器出现问题并且很难找到错误。

所以不要覆盖这个 setId/getId 方法。

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

关于java - TagSupport 中的 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18010030/

相关文章:

java - 从主线程调用时,对服务的 IPC 调用会导致 NullPointerException,但不会在按钮事件上调用

java - main 方法有 2 个不同的签名

java - Jackson 自定义解串器委托(delegate)恢复为默认值

java - 升级到Struts 2.3.16.3后s :submit does not work

java - 在 JSP 上单击提交后出现错误的 URL

java - 我正在将图像上传到 Firebase Storage,然后需要将图像 URL 作为文本添加到 Firebase 数据库中

html - 使用 jSTL 在现有选择标签上设置所选选项

javascript - 如何在按钮标签内使用 if 条件

java - 如何在发送响应后设置 session 变量?

java - 将字符串数组值传递给 sql IN 条件