網頁的 session 概念是現在網路應用程式都會使用的技術,而在 Java Servlet 中如果想要監控伺服器所有產生的 session,並做一些統計分析或記錄,可以透過實作 HttpSessionListener
這個介面(interface)的方式來達到。
HttpSessionListener
這個界面中定義了以下兩個函數:
sessionCreated(HttpSessionEvent se)
:用來處理每個 session 產生後,所要執行的動作。sessionDestroyed(HttpSessionEvent se)
:用來處理每個 invalidated 或 expired 之後的 session 所要執行的動作。
以下是實際的範例程式:
package com.sealmemory; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class SessionCounterListener implements HttpSessionListener { private static int totalActiveSessions; public static int getTotalActiveSession(){ return totalActiveSessions; } @Override public void sessionCreated(HttpSessionEvent arg0) { totalActiveSessions++; System.out.println("sessionCreated - add one session into counter"); } @Override public void sessionDestroyed(HttpSessionEvent arg0) { totalActiveSessions--; System.out.println("sessionDestroyed - deduct one session from counter"); } }
這裡我們除了實作 sessionCreated(HttpSessionEvent se)
與 sessionDestroyed(HttpSessionEvent se)
之外,也令另外建立一個 totalActiveSessions
變數,記錄目前的 session 個數,在 session 時就加一,刪除時就減一。
寫好了 listener 的程式之後,接下來要把它放進伺服器中執行,傳統的方式是寫在 web application 的 deployment descriptor(web.xml)中,語法如下:
<web-app ...> <listener> <listener-class>com.mkyong.SessionCounterListener</listener-class> </listener> </web-app>
其實就是把我們實作的類別寫上去而已,這樣就完成了,至於產生物件的動作伺服器會自己處理。
如果你只有實作 HttpSessionListener
但卻沒有將類別的完整路徑寫入 web.xml 中的話,是不會有任何效果的,所以請記得要加入上面那幾行設定。
如果是在 Java Servlet 3.0 之後的版本,也可以透過 ServletContext.addListener()
的方式把剛剛我們實作的 listener 類別加入伺服器中,或是使用 @WebListener
這個 annotation,這樣就可以不用去更動到 web.xml 設定檔,就像這樣:
@WebListener public class SessionCounterListener implements HttpSessionListener { // ... }
另外如果是 Java Servlet 3.0 以後的版本(Tomcat 7 或 GlassFish 3.x 等伺服器),HttpSessionListener.sessionDestroyed()
在 application 或是伺服器關閉時也會被呼叫,但如果是舊版的標準在這種情況似乎不會呼叫這個函數(請參考 stackoverflow)。
這裡要注意一點,因為這個 listener 是給伺服器呼叫的,它會影響到整個 web application,也就是說整個 web application 中的所有 sessions 在產生或刪除時,伺服器都會呼叫這兩個函數來處理。
另外,在這裡我們所實作的方式是無法分辨 session 是被 invalidate 還是因為 timeout 而被刪除的,如果想分辨這兩種方式就要使用其他的方法。
參考資料:Mkyong.com、XYZWS、HttpSessionListener