2008-11-18 208 views
16

在我的web應用程序中,當用戶登錄時,我將他的Id添加到servlet中有效ID的向量中,當他註銷時,我從向量中刪除了他的Id,以便可以看到有多少當前用戶處於活動狀態,如果用戶忘記註銷,我的servelt生成的html有:如何檢測瀏覽器關閉?

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

在標籤中自動註銷他。

但我注意到很多用戶都永遠在,永遠不會登出。我發現了爲什麼,通過關閉瀏覽器,他們從不手動或自動註銷,所以他們的用戶ID將永遠不會從有效的用戶ID矢量中移除。

所以,我的問題是:如何檢測用戶關閉其瀏覽器,所以我的servlet可以從向量中刪除其ID?


我看到一些光在隧道的盡頭,但仍有一個問題,我的程序有這樣的事情:

活躍用戶列表:

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

我如何從會話監聽器知道哪個用戶的會話已結束,因此將他從我的列表中刪除?

我希望當會話結束時,HttpServlet的destroy()方法會被調用,並且我可以刪除那裏的用戶標識,但是當用戶關閉瀏覽器時它不會被調用,爲什麼?當會話關閉時,HttpServlet中還有其他方法嗎?

回答

13

在服務器端無法知道瀏覽器已關閉(除非您使用一些JavaScript將消息發送到服務器)。怎麼會有?想想HTTP如何工作 - 一切都是請求和響應。

但是,應用程序服務器將跟蹤Sessions何時處於活動狀態,甚至會告訴您Session何時已被銷燬(例如由於超時)。看看this page,看看如何配置HttpSessionListener來接收這些事件。然後,您可以簡單地跟蹤活動會話的數量。

活動會話的數量將落後於當前用戶的實際數量,因爲在會話超時之前必須經過一段(可配置)時間;但是,這應該有點接近(可以降低會話超時以提高準確性),並且它比1)自己跟蹤Sessions或2)在瀏覽器關閉時向服務器發送一些異步JavaScript(比如,不保證被髮送)。

+0

順便說一句 - 我不知道我是怎麼鏈接的代碼將在羣集/多虛擬機環境中工作。我會懷疑不太好。 – 2008-11-18 18:56:18

+0

此鏈接http://www.stardeveloper.com/articles/display.html?article=2001112001&page=1已損壞。更新你的答案。 – OO7 2014-12-02 08:07:09

3

在JavaScript中,你可以使用onbeforeclose事件傳遞一個回調到服務器,當用戶關閉瀏覽器。

我通常使用同步Ajax調用做到這一點。

+0

沒有,看到我的答案...... – PhiLho 2008-11-18 21:06:50

7

我建議你刪除的ID時,Servlet引擎破壞了會議。註冊一個HttpSessionListener,當調用sessionDestroyed()時刪除用戶的ID。

Diodeus的想法只會幫助您檢測會話是否立即結束。

2

還有就是做你想做什麼沒有萬無一失的方法,但都sblundy和Diodeus有將覆蓋大多數情況下的計劃。對於在瀏覽器中關閉Javascript,或者他們的互聯網連接斷開或電源熄滅的用戶,您無能爲力。你應該在一段時間不活動之後剔除會話(我認爲這是sblundy關於會話銷燬的建議)。

2

最近我不得不這麼做,經過一番搜索之後,我在網絡上發現了一些解決方案......所有這些解決方案都無法通用!

onbeforeclose和onclose事件用於此任務。但有兩種捕獲方式:當用戶重新加載頁面時甚至只是更改當前頁面時會觸發它們。有技巧,看該事件實際上是一個窗口/頁/標籤關閉(看一些DOM屬性上的閉幕活動失控去),但是:

  • 他們是依賴於瀏覽器
  • 的招數沒有證件,從而脆
  • 而實際上他們一起瀏覽器的版本/更新而變化...

最糟糕的是,這些事件現在大多數流行的瀏覽器忽略,因爲他們已經被流氓廣告彈出窗外被濫用瀏覽器關閉時。它們並未在Safari,Opera,IE7等中被解僱。

正如指出的那樣,大多數使用登錄的Web應用程序會在一段時間後摧毀用戶會話,例如。半小時。我被要求退出瀏覽器關閉以更快速地釋放寶貴的資源:許可證。因爲用戶經常忘記註銷...

我給出的解決方案是定期(例如1分鐘)通過Ajax請求(發送用戶ID)服務器ping服務器。如果服務器未收到3分鐘的ping命令,則會斷開用戶連接。

+0

除了必須自己編寫Ajax和服務器端處理程序,重新發明輪子之外,這與使用HttpSessionListener的功能非常相似。 – 2008-11-19 16:05:08

0

這裏是一個骯髒的方式來完成「檢測瀏覽器關閉」 我發現在這個網站上的某個論壇上,當我再次找到它時,我會鏈接到它。

向http響應添加額外的標頭。當有額外的請求進來時,它們將包含這些額外的標題。您可以檢查這些標題,如果它們不存在,您可以終止會話,因此會開始一個新的標題。雖然這不會「通知」您瀏覽器已關閉,但它可以告訴您是否有人關閉了窗口並嘗試返回,因爲您添加的標題將會丟失。

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.