使用监听器监听会话
当会话发生变化时,web容器将通知应用程序这些变化,通过发布订阅模式实现。
如此一来可以将修改会话和监听会话变化的代码解耦。
ServletAPI中定义了几种监听器,通过实现某个监听器的接口来订阅某个事件。
具体配置可以使用部署描述符配置<listener>
或者使用注解@javax.servlet.annontation.WebListener
(不要同时使用)
Servlet3.0/JEE6开始,可以使用ServletContext的addListener方法以编程的方式注册。
javax.servlet.http.HttpSessionBindingListener
接口比较特殊监听器接口,不需要为它配置部署描述符以及注解,如果某个类实现了该接口,那么它自己的状态作为会话特性
最常用的两个会话监听器javax.servlet.http.HttpSessionListener
以及javax.servlet.http.HttpSessionIdListener
。
例如:
创建类SessionListener实现这两个然后添加注解
@WebListener
public class SessionListener implements HttpSessionListener,HttpSessionIdListener{...}
或者在部署描述符(web.xml)中配置
<listener>
<listener-class>com.test.SessionListener</listener-class>
</listener>
-
其中HttpSessionListener包含两个方法
sessionCreated
/sessionDestroyed
,sessionCreate将在创建session时调用,sessionDestroyed将在session失效时触发,如调用invalidate方法或过期 -
其中HttpSessionIdListener包含方法
sessionIdChanged
,sessionIdChanged将在请求的changeSessionId方法改变会话ID时调用该方法
有时在没有浏览器访问Tomcat的情况下,出现了销毁会话的记录,这是因为Tomcat在关闭时,会把会话持久化到文件系统中,Tomcat在重启时,会把持久化到文件系统的会话恢复,恢复完毕后发现该会话已经过期,触发销毁。
@WebListener
public class SessionListener implements HttpSessionListener, HttpSessionIdListener
{
private SimpleDateFormat formatter =
new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss");
@Override
public void sessionCreated(HttpSessionEvent e)
{
System.out.println(this.date() + ": Session " + e.getSession().getId() +
" created.");
SessionRegistry.addSession(e.getSession());
}
@Override
public void sessionDestroyed(HttpSessionEvent e)
{
System.out.println(this.date() + ": Session " + e.getSession().getId() +
" destroyed.");
SessionRegistry.removeSession(e.getSession());
}
@Override
public void sessionIdChanged(HttpSessionEvent e, String oldSessionId)
{
System.out.println(this.date() + ": Session ID " + oldSessionId +
" changed to " + e.getSession().getId());
SessionRegistry.updateSessionId(e.getSession(), oldSessionId);
}
private String date()
{
return this.formatter.format(new Date());
}
}
public final class SessionRegistry
{
private static final Map<String, HttpSession> SESSIONS = new Hashtable<>();
public static void addSession(HttpSession session)
{
SESSIONS.put(session.getId(), session);
}
public static void updateSessionId(HttpSession session, String oldSessionId)
{
synchronized(SESSIONS)
{
SESSIONS.remove(oldSessionId);
addSession(session);
}
}
public static void removeSession(HttpSession session)
{
SESSIONS.remove(session.getId());
}
public static List<HttpSession> getAllSessions()
{
return new ArrayList<>(SESSIONS.values());
}
public static int getNumberOfSessions()
{
return SESSIONS.size();
}
private SessionRegistry()
{
}
}