8.3 SessionListeners 一共有四个HttpSession相关的监听器接口:HttpSessionListener,HttpSessionActivationListener、HttpSessionAttributeListener和HttpSessionBindingListener。这四个接口都在javax.servlet.http包中,下面分别对它们进行介绍。
8.3.1HttpSessionListener 当一个HttpSession创建或者销毁时,容器都会通知所有的HttpSessionListener监听器,HttpSessionListener接口有两个方法:sessionCreated和sessionDestroyed:
1 2 void  sessionCreated (HttpSessionEvent event) void  sessionDestroyed (HttpSessionEvent event) 
这两个方法都可以接收到一个继承于java.util.Event的HttpSessionEvent对象。可以通过调用形参列表中的HttpSessionEvent对象的getSession方法来获取当前的HttpSession。getSession方法如下:
1 HttpSession getSession ()  
实例 app08a应用中的SessionListener类。这个监听器来统计HttpSession的数量。它使用了一个AtomicInteger对象来统计,并且将这个对象保存成ServletContext范围的属性。每当有一个HttpSession被创建时,这个AtomicInteger对象就会加一。每当有一个HttpSession被销毁时,这个AtomicInteger对象就会减一。所以这个对象会保存着当前存活的HttpSession数量。这里使用了AtomicInteger 来代替Integer类型是为了保证能同步进行加减的操作。
SessionListener类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 package  app08a.listener;import  java.util.concurrent.atomic.AtomicInteger;import  javax.servlet.ServletContext;import  javax.servlet.ServletContextEvent;import  javax.servlet.ServletContextListener;import  javax.servlet.annotation.WebListener;import  javax.servlet.http.HttpSession;import  javax.servlet.http.HttpSessionEvent;import  javax.servlet.http.HttpSessionListener;@WebListener public  class  SessionListener     implements          HttpSessionListener ,         ServletContextListener {          @Override      public  void  contextInitialized (ServletContextEvent sce)      {         ServletContext  servletContext  =               sce.getServletContext();         servletContext.setAttribute("userCounter" ,             new  AtomicInteger ());     }          @Override      public  void  contextDestroyed (ServletContextEvent sce)      {}               @Override      public  void  sessionCreated (HttpSessionEvent se)      {         HttpSession  session  =  se.getSession();         ServletContext  servletContext  =              session.getServletContext();         AtomicInteger  userCounter  =               (AtomicInteger) servletContext                 .getAttribute("userCounter" );                  int  userCount  =  userCounter.incrementAndGet();         System.out.println("userCount incremented to :"              + userCount);     }          @Override      public  void  sessionDestroyed (HttpSessionEvent se)      {         HttpSession  session  =  se.getSession();         ServletContext  servletContext  =               session.getServletContext();         AtomicInteger  userCounter  =              (AtomicInteger) servletContext                 .getAttribute("userCounter" );                  int  userCount  =  userCounter.decrementAndGet();         System.out.println("----------"              + " userCount decremented to:"              + userCount);     } } 
SessionListener类实现了ServletContextListener和HttpSessionListener接口。所以需要实现这两个接口的所有方法。
contextInitialized方法说明 contextInitialized方法创建了一个AtomicInteger对象并将其保存在ServletContext的userCounter属性中。由于是在应用启动的时候创建,因此这个AtomicInteger对象的初始值为0。
1 2 3 4 5 6 7 8 9 @Override public  void  contextInitialized (ServletContextEvent sce) {     ServletContext  servletContext  =           sce.getServletContext();     servletContext.setAttribute("userCounter" ,         new  AtomicInteger ()); } 
sessionCreated方法说明 sessionCreated方法在每个HttpSession创建时被调用。当有HttpSession创建时,从ServletContext中获取userCounter属性。然后调用userCounter的incrementAndGet 方法让计数加一。最后在控制台将userCounter的值打印出来,可以直观地看到效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Override public  void  sessionCreated (HttpSessionEvent se) {     HttpSession  session  =  se.getSession();     ServletContext  servletContext  =          session.getServletContext();     AtomicInteger  userCounter  =           (AtomicInteger) servletContext             .getAttribute("userCounter" );          int  userCount  =  userCounter.incrementAndGet();     System.out.println("userCount incremented to :"          + userCount); } 
sessionDestroyed方法说明 sessionDestroyed方法会在HttpSession销毁之前被调用。这个方法的实现和sessionCreated类似,只不过对userCounter改为减一操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Override public  void  sessionDestroyed (HttpSessionEvent se) {     HttpSession  session  =  se.getSession();     ServletContext  servletContext  =           session.getServletContext();     AtomicInteger  userCounter  =          (AtomicInteger) servletContext             .getAttribute("userCounter" );          int  userCount  =  userCounter.decrementAndGet();     System.out.println("----------"          + " userCount decremented to:"          + userCount); } 
运行效果 可以通过不同的浏览器访问countries.jsp页面来查看监听器的效果,下面是countries.jsp的访问URL:http://localhost:8080/app08a/countries.jsp Java IDE控制台会打印如下信息:
1 userCount incremented to :1 
用同一个浏览器再次访问这个URL并不会改变userCounter,因为这属于同一个HttpSession。使用不同的浏览器访问才能增加userCounter的值。这时候控制台打印内容如下:
1 2 userCount incremented to :1 userCount incremented to :2 
如果你有时间等待HttpSession过期的话,在控制台也能看到HttpSession销毁时打印的信息,如下所示:
1 2 ---------- userCount decremented to:1 ---------- userCount decremented to:0