如何检测浏览器closures?

在我的web应用程序中,当用户login时,我将他的Id添加到servlet中的有效ID的向量中,当他注销时,我从向量中删除了他的Id,以便可以看到有多less当前用户处于活动状态用户忘记注销,我的servelt生成的html有:

<meta http-equiv="Refresh" content="30; url=My_Servlet?User_Action=logout&User_Id=1111"> 

在标签中自动登出他。

但是我注意到很多用户永远都不会忘记。 我发现,为什么通过closures他们的浏览器,他们从来没有手动或自动注销,所以他们的用户ID将永远不会从有效的用户IDvector中删除。

所以,我的问题是:如何检测用户closures他们的浏览器,所以我的servlet可以从vector中删除他们的Id?


我在隧道尽头看到了一些灯光,但仍然有一个问题,我的程序有这样的情况:

活动用户列表:

 User_1 : Machine_1 [ IP_1 address ] User_2 : Machine_2 [ IP_2 address ] User_3 : Machine_3 [ IP_3 address ] ... 

我怎么知道,从会话监听器,哪个用户的会话已经结束,因此将他从我的列表中删除?

我希望当会话结束时,HttpServlet的destroy()方法将被调用,我可以在那里删除用户标识,但是当用户closures浏览器时它不会被调用,为什么呢? 当会话closures时,HttpServlet中还有其他的方法吗?

在服务器端没有办法知道浏览器已经closures(除非你使用JavaScript来发送消息到服务器)。 怎么会有? 想想HTTP如何工作 – 一切都是请求和响应。

但是,应用程序服务器将跟踪会话何时处于活动状态,甚至会告诉您何时会话被销毁(例如由于超时)。 看看这个页面 ,看看如何configuration一个HttpSessionListener来接收这些事件。 那么你可以简单地跟踪活动会话的数量。

活动会话的数量将落后于当前用户的实际数量,因为在会话超时之前必须经过一段(可configuration)时间; 然而,这应该是有点接近(你可以降低会话超时,以提高准确性),这是比自己跟踪会议或2)发送一些asynchronous的JavaScript到服务器时closures浏览器(这不保证被发送)。

我build议你在Servlet引擎破坏会话的时候删除ID。 注册一个HttpSessionListener ,当sessionDestroyed()被调用时,删除用户的ID。

Diodeus的想法只会帮助你发现会议结束了。

在JavaScript中,您可以使用onbeforeclose事件在用户closures浏览器时将callback传递给服务器。

我通常使用同步Ajax调用来做到这一点。

有没有万无一失的方法来做你想做的事情,但sblundy和Diodeus有计划,将涵盖大多数情况下。 对于在浏览器中closuresJavascript,或者互联网连接断开或电源断开的用户,您无能为力。 你应该在一段时间不活动之后剔除会话(我认为这是sblundy关于会话销毁的build议)。

最近我不得不这样做,经过一番search,我发现了一些在networking上的解决scheme…所有这些都不是普遍的工作!

onbeforeclose和onclose事件用于此任务。 但有两个捕获:当用户重新加载页面,甚至只是改变当前页面时,它们被触发。 有一些技巧,看看事件实际上是一个窗口/页面/标签closures(查看一些Dom属性去closures事件haywire),但:

  • 它们依赖于浏览器
  • 这些技巧是无证的,因此很脆弱
  • 而实际上,他们沿着浏览器版本/更新…

而最糟糕的是,这些事件现在被大多数现代浏览器所忽视,因为当浏览器closures时,它们被stream氓广告滥用。 他们没有在Safari,Opera,IE7等中被解雇

正如所指出的那样,大多数使用login的Web应用程序会在一段时间后破坏用户会话, 半小时。 我被要求退出浏览器closures以更快速地释放宝贵的资源:许可证。 因为用户经常忘记注销…

我给出的解决scheme是定期(例如1分钟)通过Ajax请求(发送用户ID)服务器进行ping。 如果服务器未收到3分钟的ping,则断开与用户的连接。

这里是一个肮脏的方式来完成“检测浏览器closures”,我发现在这个网站上的某个论坛上,当我再次find它,我会链接到它。

向http响应添加额外的头文件。 当额外的请求进来时,他们将包含这些额外的标题。 你可以检查这些标题,如果它们不存在,你可以杀死会话,所以一个新的会开始。 虽然这不会“通知”您浏览器是否closures,但可以告诉您是否有人closures了窗口并尝试返回,因为您添加的标题将会丢失。

  wrapper.setHeader("Cache-Control", "no-cache, no-store, must- revalidate"); wrapper.setHeader("Pragma", "no-cache"); wrapper.setDateHeader("Expires", 0); Where wrapper is a response wrapper. if (wrapper.getHeaderNames().size() < the number of headers you are expecting) request.getSession().invalidate(); Not perfect but it might help someone.