如何检测浏览器关闭?

16

在我的Web应用程序中,当用户登录时,我将他的Id添加到servlet中有效Id的向量中,当他注销时,我从向量中删除他的Id,以便我可以查看有多少当前用户处于活动状态。如果用户忘记注销,则我的servlet生成的HTML为:

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

在标签中自动注销用户。

但我注意到很多用户一直在线,从未注销。我发现原因是他们关闭了浏览器,从未手动或自动注销,因此他们的用户 ID 将永远不会从有效用户 ID 向量中删除。

那么,我的问题是:如何检测到用户关闭浏览器,以便我的 Servlet 可以从向量中删除他们的 ID?


我看到了一线希望,但还存在一个问题,我的程序有类似于以下内容:

Active User List:

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

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

我希望当会话结束时,HttpServlet的destroy()方法会被调用,然后我可以在其中删除用户ID,但是当用户关闭浏览器时,它永远不会被调用,为什么?还有没有其他的方法在HttpServlet中,在会话关闭时被调用?

5个回答

14

除非您使用一些JavaScript向服务器发送消息,否则无法从服务器端知道浏览器何时关闭。怎么可能呢?想想HTTP是如何工作的 - 一切都是请求和响应。

但是,应用程序服务器将跟踪Sessions何时处于活动状态,甚至会告诉您Session何时被销毁(例如由于超时)。请参阅此页面了解如何配置HttpSessionListener以接收这些事件。然后,您可以简单地跟踪活动会话的数量。

活动会话的数量将滞后于当前用户的实际数量,因为必须经过一定的(可配置的)时间才能使会话超时;但是,这应该相当接近(您可以降低会话超时时间以提高准确性),而且比1)自己跟踪Sessions或2)关闭浏览器时发送一些异步JavaScript到服务器要干净得多,而且更容易控制(不能保证发送)。


顺便说一句 - 我不知道我链接的代码在集群/多个虚拟机环境中如何运行。我会怀疑它的表现不是很好。 - matt b
这个链接 http://www.stardeveloper.com/articles/display.html?article=2001112001&page=1 已经失效,请更新您的答案。 - OO7

7
我建议在Servlet引擎销毁会话时删除ID。注册一个HttpSessionListener,当调用sessionDestroyed()时删除用户的ID。

Diodeus的想法只能更快地帮助您检测到会话已结束。


3

在JavaScript中,您可以使用onbeforeclose事件在用户关闭浏览器时向服务器传递回调。

我通常使用同步的Ajax调用来实现这一点。


3

最近我不得不做这个任务,在网上搜索了一些解决方案......但是所有的解决方案都不能通用!

使用onbeforeclose和onclose事件来完成此任务。但是有两个问题:当用户重新加载页面或只是更改当前页面时,它们会被触发。有一些技巧可以查看事件是否实际上是窗口/页面/选项卡关闭(查看一些Dom属性在关闭事件上失控),但是:

  • 它们依赖于浏览器
  • 这些技巧未经记录,因此脆弱
  • 实际上它们随着浏览器版本/更新而变化……

最糟糕的是,这些事件现在被大多数现代浏览器忽略,因为恶意广告会在浏览器关闭时弹出窗口。它们在Safari、Opera、IE7等浏览器中不被触发。

正如指出的那样,大多数具有登录功能的Web应用程序在一段时间后销毁用户会话,例如30分钟。我被要求在浏览器关闭时注销以更快地释放宝贵的资源:许可证。因为用户经常忘记注销......

我提供的解决方案是定期(例如1分钟)使用Ajax请求(发送用户ID)向服务器ping。如果服务器连续3分钟没有收到ping,它将断开用户连接。


这在功能上与使用 HttpSessionListener 基本相同,只是你不得不编写 Ajax 和服务器端处理程序,重新发明轮子。 - matt b
1
你在开玩笑吧?HttpSessionListener是一个接口,它不提供Ajax或魔法。 - PhiLho

2

要做你尝试做的事情没有绝对可靠的方法,但是sblundy和Diodeus都有计划可以涵盖大多数情况。如果有人在浏览器中关闭JavaScript、网络连接断开或电力中断,则您无法采取任何措施。您应该在一段时间内剔除不活跃的会话(我认为sblundy建议监听会话销毁就是这样做的)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接