網頁的 session 概念是現在網路應用程式都會使用的技術,而在 Java Servlet 中如果想要監控伺服器所有產生的 session,並做一些統計分析或記錄,可以透過實作 HttpSessionListener 這個介面(interface)的方式來達到。

HttpSessionListener 這個界面中定義了以下兩個函數:

  1. sessionCreated(HttpSessionEvent se):用來處理每個 session 產生後,所要執行的動作。
  2. 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.comXYZWSHttpSessionListener