我有以下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
没有被叫?
为什么? 是否有解决方法来准确记录会话被销毁的时间(当用户关闭浏览器时)?这不应该是浏览器的问题,在关闭会议时终止会话吗?
我是否需要为此实现任何接口?
谢谢!
答案 0 :(得分:39)
服务器如何知道浏览器关闭或标签何时关闭?此时,浏览器不会向服务器发送任何内容。
这是HTTP的基本部分 - 它是一个请求/响应协议,而不是“永久开放的对话”,您可以在其中判断一方是否离开了对话。把它想象成一系列电报而不是电话 - 当你收到最后一封电报时,你无法分辨。
您需要设计自己的方式 - 避免需要知道浏览器何时关闭。有一些丑陋的黑客可以解决它 - 例如,让AJAX用心跳信息轮询服务器 - 但改变设计是一个更好的解决方案。
答案 1 :(得分:6)
注意:如下面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方法。
答案 2 :(得分:1)
由于大量工作,浏览器不会通知服务器窗口已关闭,因此Java无法知道何时销毁会话。因此,超时就绪,并且是服务器知道可以解除此会话的第一个。
您可以尝试在javascript事件document.onunload上播放ajax调用 https://developer.mozilla.org/en/DOM/window.onunload但是,当您执行此操作时,您需要确保用户不在您的网站中。
答案 3 :(得分:1)
会话对象位于服务器中并由服务器控制。只有服务器可以创建或销毁会话。因此,如果客户端关闭,会话将一直存在,直到它过期。客户端只能向服务器建议它可以销毁某些会话。此请求必须以某种方式显式。因此,当您关闭浏览器窗口时,没有对服务器的隐式请求,通知它必须销毁给定的会话。
答案 4 :(得分:1)
如果您需要在浏览器窗口/选项卡关闭时销毁会话,您可以将一个JavaScript处理程序附加到onunload事件,该事件对调用kill会话的资源进行某种AJAX调用。
请注意,onunload事件并不总是触发,因此它并不完全值得信赖。一种可靠的方式可能是使用“心跳”系统。
答案 5 :(得分:0)
正如Eric所说,浏览器上的unload事件可以调用一个javascript函数,而javascript函数又可以通过一个记录你的servlet访问一个url。您无需等待servlet的实际响应。
Web浏览器通过http协议与服务器交互,这是无状态的。
答案 6 :(得分:0)
有一些黑客知道 以下用户关闭浏览器时的销毁会话代码
客户方:
<script src="jquery path"></script>
<script>
window.onunload = function(){ $.get("${request.contextPath}/logout"); }
</script>
服务器端:为“/ 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
<listener>
<listener-class>SesListener</listener-class>
</listener>
答案 7 :(得分:-1)
您只需验证您的会话用户是否为空:
if (session.getAttribute("user") != null )
sessionsetAttribute("user","null");