springboot 用监听器统计在线人数,小案例
程序员文章站
2024-03-20 10:24:52
...
本文在springboot 的项目,用HttpSessionListener 监听器(监听器的其中一种) 统计在线人数,实质是统计session 的数量。
思路很简单,但是有个细节没处理好,让我调试了大半天,才把bug搞好。
先写个HttpSessionListener 监听器。count 是session的数量(人数),session 创建的时候,会触发监听器的sessionCreated 方法,session销毁的时候,会触发监听器的sessionDestroyed 方法。 在监听器中计算完人数count,把他放进servletContext(可以理解为一个仓库,任意请求可以存储和获取里面的属性)。
注意监听器加上@WebListener,这样就不用配置。
@WebListener
public class OnLineCount implements HttpSessionListener {
public int count=0;//记录session的数量
//监听session的创建,synchronized 防并发bug
public synchronized void sessionCreated(HttpSessionEvent arg0) {
System.out.println("【HttpSessionListener监听器】count++ 增加");
count++;
arg0.getSession().getServletContext().setAttribute("count", count);
}
@Override
public synchronized void sessionDestroyed(HttpSessionEvent arg0) {//监听session的撤销
System.out.println("【HttpSessionListener监听器】count-- 减少");
count--;
arg0.getSession().getServletContext().setAttribute("count", count);
}
}
接着写一个查询session 数量的controller,我开始的时候是像下面这样写的,是错误的!
从servletContext 中取出count ,把count返回前端。
@RequestMapping("/count")
@ResponseBody
public String count(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
Object count=httpServletRequest.getServletContext().getAttribute("count");
return "count : "+count;
}
这样是错误的,测试你会发现,页面看到count 是null ,因为没有创建session,没有触发监听器的统计方法。于是改一下:
@Controller
public class IndexController {
@RequestMapping("/count")
@ResponseBody
public String count(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
HttpSession session = httpServletRequest.getSession();
Object count=session.getServletContext().getAttribute("count");
return "count : "+count;
}
}
HttpSession session = httpServletRequest.getSession(); 作用:该用户如果没有sesision则创建session ,有则取得session不创建。
有2个方法可以解决这个问题,一个是在关闭网页的时候,前端去调用一个方法把session销毁。另一个更好的方法是,让服务器记得原来那个session,即把原来的sessionId 记录在浏览器,下次打开时,把这个sessionId发送过去,这样服务器就不会重新创建。
代码修改如下:
@Controller
public class IndexController {
@RequestMapping("/count")
@ResponseBody
public String number(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
try{ //把sessionId记录在浏览器
Cookie c = new Cookie("JSESSIONID", URLEncoder.encode(httpServletRequest.getSession().getId(), "utf-8"));
c.setPath("/");
//先设置cookie有效期为2天,不用担心,session不会保存2天
c.setMaxAge( 48*60 * 60);
httpServletResponse.addCookie(c);
}catch (Exception e){
e.printStackTrace();
}
HttpSession session = httpServletRequest.getSession();
Object count=session.getServletContext().getAttribute("count");
return "count : "+count;
}
}
测试达到效果。