HttpSession オブジェクトには、ステートを簡単かつ強力に管理できるようにする API が用意されています。HttpSession オブジェクトにはイベントリスナが 3 つあります。
HttpSessionListener
HttpSessionAttributeListenerHttpSessionActivationListenerServletContext リスナの場合と同様に、JRun はイベントオブジェクトをセッションリスナ内の各メソッドに渡します。リスナはこれらのオブジェクトを介して Session オブジェクト、Session オブジェクトの属性、および ServletContext オブジェクトにアクセスできます。
HttpSession イベントが発生すると、これらのインターフェイスが実装しているメソッドをトリガーできます。次の表に、これらのインターフェイスのメソッドと、JRun にこれらのメソッドを呼び出させるイベントを示します。
HttpSessionListener を使用して、ロギングまたはパーシスタンスコードをアプリケーションに入れることができます。このリスナは、アプリケーションにログインしているユーザーの数を追跡する際にも役立ちます。この例では、セッションが作成されるたびにカウンタを 1 つ増やし、セッションが廃棄されるたびに 1 つ減らします。
次の行のように、セッションを作成するリソースがリクエストされると、JRun はセッションを作成します。
HttpSession session = request.getSession(true);
次の行のように、セッションがタイムアウトになるか、明示的に廃棄されると、JRun はセッションを廃棄します。
session.invalidate();
クライアントからのリクエストなしに MaxInactiveInterval が経過すると、セッションはタイムアウトになります。JRun がタイムアウトになるまでのデフォルト設定は 1800 秒 (30 分) です。セッション設定の詳細については、『JRun 管理者ガイド』を参照してください。
セッションオブジェクトは Cookie オブジェクトとして頻繁にインスタンス化されます。それによって、Cookie オブジェクトとしてセッションでオペレーションを実行できますが、制限もあります。たとえば、Cookie の MaxAge が -1 に設定されている場合は、ブラウザを閉じたときにクライアント上で Cookie が廃棄されます。サーバはクライアントが閉じたことを検出できないため、HttpSessionListener.sessionDestroyed イベントは通知されません。
JRun は、セッションオブジェクトが最初に作成または廃棄されたときに、次のメソッドを使用して HttpSessionListener に通知します。
sessionCreated(HttpSessionEvent event)
sessionDestroyed(HttpSessionEvent event)HttpSessionListenerEvent オブジェクトには次の 1 つのメソッドがあります。
JRun は、Session オブジェクトの属性が追加または削除されるか、または Session オブジェクトの属性の値が変更されると、次のメソッドを使用して HttpSessionAttributeListener に通知します。
attributeAdded(HttpSessionBindingEvent event)
attributeRemoved(HttpSessionBindingEvent event)attributeReplaced(HttpSessionBindingEvent event)
Session オブジェクトの属性は、HttpSession オブジェクトのみがアクセス可能です。ServletContext のオブジェクト名に合わせるには、イベントオブジェクト
HttpSessionBindingEvent の名前を HttpSessionAttributeEvent とする方が適切です。
HttpSessionBindingEvent オブジェクトは HttpSessionEvent オブジェクトから getSession メソッドを継承します。セッション属性にアクセスできるメソッドが他に 2 つあります。
getName()
getValue()
単純な HttpSession イベントリスナの例を次に示します。このイベントリスナは
HttpSessionListener のメソッドを実装します。これらのいずれかのイベントが発生すると、標準出力に行が出力されます。セッションが作成されると、このリスナはセッション ID と作成日を標準出力に出力します。
...
public final class SessionLogger implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
System.out.println("作成されたセッション");
HttpSession session = event.getSession();
String sid = session.getId();
long time = session.getCreationTime();
System.out.println("新規セッション ID:" + sid);
System.out.println("作成されたセッション @ " + time);
}
public void sessionDestroyed(HttpSessionEvent event) {
System.out.println("セッション " + event.getSession().getId() + " 廃棄");
}
}
HttpSession リスナの用途の 1 つに、セッションを保管および追跡するためのコードの集中化があります。すべてのデータベースコードをリスナに入れ、サーブレットと JSP を保管すると、追跡情報の詳細とは別にセッションオブジェクトを操作できます。
さまざまなイベントの呼び出しを予測できるため、このセットアップは、Sun の『Core J2EE Patterns』に記載されている Intercepting Filter パターン (Decorator Filter パターンとも呼ばれる) に似ています。
package jrunsamples.events; import javax.servlet.*;
import javax.servlet.http.*; import java.sql.*; import javax.sql.*; import javax.naming.*;
public final class SessionWatcher implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
//Session オブジェクトを介して ServletContext オブジェクトにアクセスすることもでき
ます。
String datasource_name = (String) event.getSession().
getServletContext().getAttribute("datasource_name");
HttpSession session = event.getSession();
String sid = session.getId();
long time = session.getCreationTime();
//セッション ID、作成日、およびセッション変数の値をデータベースに追加します。
String sqlstmt = "INSERT INTO SESSIONS VALUES(?,?,?)";
try {
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(datasource_name);
Connection conn = ds.getConnection();
PreparedStatement ps = conn.prepareStatement(sqlstmt);
ps.setString(1,sid);
ps.setLong(2,time);
ps.setInt(3, 1); //デフォルト値は 1 に設定されています。
ResultSet rs = ps.executeQuery();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
ps.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
次の単純な HttpSession イベントリスナの例では、HttpSessionAttributeListener のメソッドを実装します。これらのいずれかのイベントが発生すると、標準出力に行が出力されます。属性の値が変更されると、このイベントリスナはセッション属性のすべてを標準出力に出力します。
public final class SessionAttrLogger implements
HttpSessionAttributeListener {
public void attributeAdded(HttpSessionEvent event) {
System.out.println("追加されたセッション属性");
}
public void attributeRemoved(HttpSessionEvent event) {
System.out.println("削除されたセッション属性");
}
public void attributeReplaced(HttpSessionEvent event) {
System.out.println("変更されたセッション属性");
HttpSession session = event.getSession();
Enumeration enum = session.getAttributeNames();
while (enum.hasMoreElements()) {
String attrname = (String)enum.nextElement();
System.out.println(attrname + "=" +
session.getAttribute(attrname));
}
}
}
JRun は、セッションがアクティブになるかパッシベートされると、
HttpSessionActivationListener に通知します。
パッシベートは、JRun がセッションを無効にしないが、リソースを解放するためにセッションをディスクにバックアップした場合や、"ミラーリング" された JRun サーバに障害が発生し、別の JRun サーバがそのセッションを引き受けた場合に発生します。これは、セッションパーシスタンスとも呼ばれます。
アクティブ化は、セッションをパッシベートされたクライアントがリクエストし、セッションをディスクから取得するか、新規 JRun サーバにロードする必要がある場合に発生します。
次の単純な HttpSession イベントリスナの例では、HttpSessionActivationListener インターフェイスのメソッドを実装します。これらのいずれかのイベントが発生すると、標準出力に行が出力されます。
...
public void sessionWillPassivate(HttpSessionEvent event) {
System.out.println("Session was passivated");
}
public void sessionDidActivate(HttpSessionEvent event) {
System.out.println("Session was activated");
}
...