【发布时间】:2012-08-28 17:55:14
【问题描述】:
为什么sessionDestroyed() 只在无效或超时时调用,而在服务器终止时不调用?服务器终止时如何对每个会话进行一些操作?
【问题讨论】:
-
终止是什么意思?杀死或关闭服务器?
标签: java tomcat servlets servlet-listeners
为什么sessionDestroyed() 只在无效或超时时调用,而在服务器终止时不调用?服务器终止时如何对每个会话进行一些操作?
【问题讨论】:
标签: java tomcat servlets servlet-listeners
Java Servlet 3.0 规范规定应在服务器/应用程序关闭时调用 HttpSessionListener.sessionDestroyed()(第 11.3.4 节 关闭时的通知):
在应用程序关闭时,会以与其声明相反的顺序通知侦听器 向会话侦听器发出通知,然后再向上下文侦听器发出通知。 会话侦听器必须在上下文侦听器之前通知会话失效 收到应用程序关闭的通知。
Tomcat 7 实现了 Java Servlet 3.0 规范,应该支持您的用例。
【讨论】:
关于您的第一个问题:
为什么 sessionDestroyed() 只在失效或超时时调用,而在服务器终止时不调用?
这里解释了为什么在 Tomcat 中关闭时(至少从 Tomcat 6.0.33 开始)没有调用 sessionDestroyed(),来自 Tomcat 上的帖子:http://comments.gmane.org/gmane.comp.jakarta.tomcat.user/215644
当我请求我的 Web 应用程序时,我收到 sessionCreated,当我 从我收到 sessionDestroyed 的代码中使会话无效。 不幸的是,当我停止 Web 应用程序时,我没有收到 sessionDestroyed。
我检查了 StandardContext 停止的代码。我理解了 调用 StandardManager.stop 没问题 但是当调用 StandardManager.doUnload() 时,在它的实现中 * session.expire(false)* 被称为“假”实际上是标志 指示是否通知侦听器。因为它被调用 "false" - 不调用监听器。
这不是我的帖子,我将归功于该帖子的作者 Violeta。
该帖子提供了一种修补StandardManager.java的方法。
如果您不想修改该类(我个人尽可能避免修改属于 Application Server 的类),您可以采用其他方法。
关于你的第二个问题:
如何在服务器终止时对每个会话进行一些操作?
为什么要在服务器终止时对每个会话进行操作? Servlet 规范提供了在服务器关闭时执行代码的方法。但是,它们没有提供一种方法,您可以通过它对每个活动会话执行操作(可能是设计使然)。
正如前面的答案所提到的,How to access HTTP sessions in Java,会话管理应该由 Servlet 容器处理,您可以重新考虑您当前的应用程序方法。
对于服务器关闭时的一般处理清理,您有 ServletContextListener.contextDestroyed 和 Servlet.destroy
ServletContextListener接口提供了contextDestroyed生命周期方法
Servlet 接口提供了一个 destroy 方法,用于在服务器关闭时释放任何资源或处理任何清理工作。
【讨论】:
阅读Execute code after Glassfish Web Deployment我得到了这个问题的答案。
我们可以编写一个 ServletContextListener 在上下文加载或终止时触发,如下所示:
public class MyServlet implements ServletContextListener {
public void contextInitialized(ServletContextEvent e) {
// implementation code
}
public void contextDestroyed(ServletContextEvent e) {
// implementation code
}
}
现在,在您的情况下,将触发关闭,然后将调用 contextDestroyed() 方法。
参考:
感谢加里斯·苏罗
【讨论】: