Java:关闭选项卡或浏览器时为什么不会销毁http会话?

我有HttpSessionlistener的以下实现

public class SessionListener implements HttpSessionAttributeListener, HttpSessionListener { public void attributeAdded(HttpSessionBindingEvent event) { ... } public void attributeRemoved(HttpSessionBindingEvent event) { ... } public void attributeReplaced(HttpSessionBindingEvent event) { } //HttpSesion creation & destruction public void sessionCreated(HttpSessionEvent event) { HttpSession session = event.getSession(); //log created time } public void sessionDestroyed(HttpSessionEvent event) { HttpSession session = event.getSession(); long destroyedTime = System.currentTimeMillis(); //log destroyed time } 

}

基本上我记录会话创建和销毁时间。 但是如果会话很长(默认为30分钟),并且用户同时关闭浏览器,那么

 sessionDestroyed 

不叫?

这是为什么 ? 是否有解决方法来准确记录会话被销毁的时间(当用户关闭浏览器时)? 难道这不是浏览器的问题,在关闭会议时终止它吗?

有什么接口我必须实现这个工作吗?

谢谢 !

服务器如何知道浏览器关闭或标签何时关闭? 此时,浏览器不会向服务器发送任何内容。

这是HTTP的基本部分 – 它是一个请求/响应协议,而不是“永久开放的对话”,您可以在其中判断一方是否离开了对话。 把它想象成一系列电报而不是电话 – 当你收到最后一封电报时,你无法分辨。

您需要设计自己的方式 – 以避免需要知道浏览器何时关闭。 有一些丑陋的黑客可以解决它 – 例如,让AJAX用心跳信息轮询服务器 – 但改变设计是一个更好的解决方案。

注意:正如jwenting在下面评论的那样,这根本不是100%安全的。 如果onunload事件没有被浏览器选项卡或窗口的关闭事件触发,那么这将失败。

我有同样的问题,并使用侵入式JavaScript事件解决它:

 window.onunload 

让我简单解释一下,假设您有一个JavaScript函数,使用jQuery将当前的Session ID发布到该Servlet以使其无效,如下所示:

 function safeexit(){ $.post("/SessionKillServlet", { SID = <%=session.getId()%> }, function(data){}); } 

要调用该函数,您只需要像这样绑定它:

 window.onunload = safeexit; //without the () 

现在,当TAB或BROWSER WINDOW关闭(或重定向)时,将调用safeexit方法。

由于大量工作,浏览器不会通知服务器窗口已关闭,因此Java无法知道何时销毁会话。 因此,超时已到位,并且是服务器首先知道可以解除此会话的第一个。

您可以尝试在javascript事件document.onunload https://developer.mozilla.org/en/DOM/window.onunload上播放ajax调用,但是当您需要确保用户不在您的站点内时做这个。

会话对象存在于服务器中并由服务器控制。 只有服务器可以创建或销毁会话。 因此,如果客户端关闭,会话将一直存在,直到它过期。 客户端只能向服务器建议它可以销毁某些会话。 此请求必须以某种方式显式。 因此,当您关闭浏览器窗口时,没有对服务器的隐式请求,通知它必须销毁给定的会话。

如果在关闭浏览器窗口/选项卡时需要销毁会话,则可能会将一个JavaScript处理程序附加到onunload事件,该事件会对调用kill会话的资源进行某种AJAX调用。

请注意,onunload事件并不总是触发,因此它不是完全值得信赖的。 一种可靠的方式可能是使用“心跳”系统。

正如Eric提到的那样,浏览器上的unload事件可以调用一个javascript函数,而javascript函数又可以通过一个记录你的servlet访问一个url。 您无需等待servlet的实际响应。

Web浏览器通过http协议与服务器交互,这是无状态的。

当用户关闭浏览器时,有一些黑客知道下面的代码用于销毁会话

客户端:

   

服务器端:为“/ logout”创建请求映射

 public void doGet(HttpServletRequest request, HttpServletResponse) { request.getSession().invalidate(); System.out.println('destroy from logout on unload browser'); } 

以下代码是可选的

想要知道会话被破坏时使用会话监听器

 // in class import javax.servlet.*; import javax.servlet.http.*; public class SesListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent se) { System.out.println("Session created..."); } public void sessionDestroyed(HttpSessionEvent se) { System.out.println("Session destroyed..."); } } //----------------------------------------- // in web.xml  SesListener  

您可以只validation您的会话用户是否为null,如:

 if (session.getAttribute("user") != null ) sessionsetAttribute("user","null");