Java監聽器案例

  • 統計當前在線用戶

- 建立監聽器類瀏覽器

 1 public class CountNumListener implements HttpSessionListener {
 2     @Override
 3     public void sessionCreated(HttpSessionEvent se) {
 4         //經過事件對象獲取ServletContext
 5         ServletContext context = se.getSession().getServletContext();
 6         Integer count = (Integer) context.getAttribute("count");
 7         if (count == null) {
 8             context.setAttribute("count",1);
 9         }
10         count++;
11         context.setAttribute("count",count);
12     }
13 
14     @Override
15     public void sessionDestroyed(HttpSessionEvent se) {
16         ServletContext context = se.getSession().getServletContext();
17         Integer count = (Integer) context.getAttribute("count");
18         count--;
19         context.setAttribute("count",count);
20     }
21 }

- 註冊監聽器服務器

1 <listener>
2     <listener-class>com.xym.listener.CountNumListener</listener-class>
3 </listener>

- 測試代碼session

 當前在線人數:${applicationScope.count}人! 併發

此方式只能統計一個近似值,由於當客戶離開網站時,服務器端的Session沒有及時銷燬,或是客戶端同時開兩個瀏覽器窗口訪問時都會形成數據的不許確。app

  • 自定義Session掃描器
 1 public class SessionScanner implements HttpSessionListener, ServletContextListener {
 2 
 3     // 常常增刪應使用鏈表容器,容器會被併發訪問,應使用同步容器
 4     private static List<HttpSession> list = Collections.synchronizedList(new LinkedList<>());
 5     private static final Object lock = new Object();
 6 
 7     @Override
 8     public void sessionCreated(HttpSessionEvent se) {
 9         HttpSession session = se.getSession();
10         System.out.println("Session被建立,ID:" + se.getSession().getId());
11         // 與定時器執行銷燬時共享鎖 不然會有併發修改異常
12         synchronized (lock) {
13             list.add(session);
14         }
15     }
16 
17     @Override
18     public void sessionDestroyed(HttpSessionEvent se) {
19         System.out.println("Session被銷燬,ID:" + se.getSession().getId());
20     }
21 
22     @Override
23     public void contextInitialized(ServletContextEvent sce) {
24         // 服務器啓動時建立一個定時器 每30秒執行任務
25         Timer timer = new Timer();
26         timer.schedule(new MyTask(),0,30*1000);
27     }
28 
29     @Override
30     public void contextDestroyed(ServletContextEvent sce) {
31 
32     }
33 
34     static class MyTask extends TimerTask{
35 
36         @Override
37         public void run() {
38             System.out.println("定時器執行!");
39             synchronized (lock) {
40                 // 應獲取可迭代修改的迭代器,用迭代器的方法移除容器內的Session
41                 ListIterator<HttpSession> iterator = list.listIterator();
42                 while (iterator.hasNext()) {
43                     HttpSession session = iterator.next();
44                     // 若是Session無活躍時長大於30秒 則摧毀
45                     if (System.currentTimeMillis() - session.getLastAccessedTime() > 30 * 1000) {
46                         session.invalidate();
47                         iterator.remove();
48                     }
49                 }
50             }
51         }
52     }
53 }

同時實現兩個監聽器,在服務器啓動時會建立定時器,在建立Session時會加入自定義的容器內自行管理,再也不由服務器管理。ide

此Session掃描器啓動的時間跟Session建立的時間會有30秒的時間差測試

相關文章
相關標籤/搜索