springboot 用监听器统计在线人数案例分析

创建HttpSessionListener 监听器

先写个HttpSessionListener 监听器。count 是session的数量(人数),session 创建的时候,会触发监听器的sessionCreated 方法,session销毁的时候,会触发监听器的sessionDestroyed 方法。 在监听器中计算完人数count,把他放进servletContext(可以理解为一个仓库,任意请求可以存储和获取里面的属性)

/**
 * @author fanghui
 */
@SpringBootApplication
@MapperScan({"com.izkml.energy.data.mapper"})
@EnableSwagger2
@EnableAsync
@EnableCaching
@ServletComponentScan //添加这个注解
public class EnergyDataApplication {
    public static void main(String[] args) {
        SpringApplication.run(EnergyDataApplication.class, args);
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowCredentials(true)
                        .allowedOrigins("*")
                        .allowedMethods("GET", "POST");
            }
        };
    }
}

controller编码

接着写一个查询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不创建。

改成这样测试,看起来是对的,但是有个问题。一个浏览器对应一个session,你打开2个浏览器,看到count是2 ,是对的。但是你关了一个浏览器,再打开,应该是2不变才对,但是变成3 了,原因是session销毁的方法没有执行,重新打开时,服务器找不到用户原来的session ,重新创建了一个session,于是有3个session了,但是浏览器只有2个,也就是模拟应该是只有2个人在线上。
有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;
    }
}

总结:这里只是一个小小的案例分析,后续还会结合不同应用业务场景来进行应用,大家可以在评论区进行评论,动一动你们的鼠标可以关注下,博文会持续分享一些干货

posted @ 2020-08-12 11:46  荭丶尘  阅读(946)  评论(0编辑  收藏  举报