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