- 建立监听器类浏览器
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秒的时间差测试