11

我刚刚在我的代码中引入了一个错误,因为我似乎误解了 jsp 标签的生命周期。

在出现错误之前,标签的工作方式是这样的:我将一些集合作为属性传递给标签,并将其显示为表格。集合从控制器传递到 JSP。

错误之后:我删除了设置集合的属性。相反,在标签中我检查集合是否为空,然后从请求中按名称获取它(使用命名约定)。

出乎我意料的是:集合最初设置在标签中之后,在后续执行中它永远不会变为 null!它仍然被定义为 TLD 中的非必需属性。

希望标签在执行之间不会保留以前的值。

4

6 回答 6

12

你自己回答了这个问题 - 它是汇集的。请参阅标签教程以了解在 java 实现中要实现的内容,以及从那里链接的页面,其中包含调用序列

ATag t = new ATag();
t.setPageContext(...);
t.setParent(...);
t.setAttribute1(value1);
t.setAttribute2(value2);
t.doStartTag();
t.doEndTag();
t.release();

也就是说,根据 API 的需要,在 doEndTag() 中重新初始化您的标签实例。(由 Julien Kronegg 更改评论,谢谢)

请注意,池化可能是容器相关的,但非常合法(并且,由于 API 设置,可能在任何地方都进行)。

于 2009-03-05T19:08:34.570 回答
8

简短的回答:你不应该自己写属性属性。通过这样做,您将清洁国家作为您的责任。

对于更长的答案,JSP 2.0 规范规定了以下内容(第 2-51 页):

  • 为特定标签出现的所有指定属性调用设置器
  • 省略的属性调用设置器(保持默认值不变,在您的情况下,内部状态为非法值)
  • 标记处理程序只能被具有相同的一组指定属性的事件重用

这三点共同保证属性属性始终正确初始化,同时仍保留默认值(在构造函数或属性的声明中定义)。作为回报,它仅在只有容器操纵属性属性(通过调用设置器)的假设下才起作用。

为了完整起见:

  • release()不应用于在标记处理程序的调用之间重置内部状态。它只保证在 GC 之前被调用,并且应该用于释放长期资源。
  • 如果要在 中初始化实例变量doStartTag(),请注意不要覆盖属性,因为此时容器已经调用了 setter。
  • doEndTag()应该可以安全地用于初始化,因为在异常情况下绝不应重复使用标记(请参阅第 2-54 页 [2])
于 2010-05-18T11:55:17.003 回答
3

JSP 1.2 规范添加了 TryCatchFinally 接口。 http://docs.oracle.com/javaee/1.4/api/javax/servlet/jsp/tagext/TryCatchFinally.html

所以看起来你应该在 doStartTag() 方法中分配资源并在 doFinally() 方法中清理。

于 2012-03-05T19:09:54.033 回答
1

所以答案是:标签被汇集到魔法池中,并在执行之间重复使用。标签规范说:

“不应设置未指定的属性/属性(使用 setter 方法)。”

于 2009-03-05T18:57:29.620 回答
0

对 Tomcat 6 的观察表明 release() 仅在容器关闭时调用。标记处理程序实例成员应在 doEndTag() 中清除实例状态。从 api 文档:

“必须重置与此实例关联的所有实例状态。”

请参阅TagSupport.doEndTag()

于 2009-06-05T20:55:53.417 回答
0

release方法是JSP使用完标签的时间段,用来让标签释放。

于 2016-04-21T00:31:16.343 回答