- 建立監聽器類瀏覽器
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
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秒的時間差測試