我刚刚在我的代码中引入了一个错误,因为我似乎误解了jsp标签的生命周期.
标签在错误之前就像这样工作:我将标签作为属性传递给某个集合,并将其显示为表格.该集合从控制器传递到JSP.
错误之后:我删除了设置集合的属性.相反,在标记中我检查集合是否为null,然后从请求中按名称获取它(使用命名约定).
我没想到的事情:收集最初在标签中设置后,在后续执行中永远不会变为空!它仍被定义为TLD中的非要求属性.
我希望标签不会保留执行之间的先前值.
你自己回答了这个问题 - 它被汇集了.有关在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设置,可能在任何地方都可以).
简短的回答:您不应该自己写属性属性.通过这样做,您可以清洁国家的责任.
对于更长的答案,JSP 2.0规范规定了以下内容(第2-51页):
调用特定事件标记的所有指定属性的调用者
不会为省略的属性调用setter (保留默认值,在您的情况下,在内部状态中为非法值)
标记处理程序只能由具有相同指定属性集的出现重用
这三个点共同保证属性属性始终正确初始化,同时仍保留默认值(在构造函数或属性声明中定义).作为回报,它只能假设只有容器操作属性属性(通过调用setter).
为了完整起见:
release()
不应该用于在标记处理程序的调用之间重置内部状态.它只能保证在GC之前被调用,并且应该用于释放长期资源.
如果要初始化实例变量doStartTag()
,请注意不要覆盖属性,因为此时容器已经调用了setter.
doEndTag()
应该可以安全地用于初始化,因为在异常的情况下不应该重复使用标记(参见第2-54页[2])