欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Springboot 配置 HttpSessionListener 不生效的详细信息

最编程 2024-05-03 16:16:59
...

背景:在Springboot的项目中单独创建了一个HttpSessionListener,但是发现sessionCreated方法无论如何都不会被调用,意味着我们根本没有监听到Session被创建,接下来我做了详细调研。

以下代码仅作参考:

Application.java

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

MyHttpSessionListener.java

@Configuration
@WebListener
@Slf4j
public class MyHttpSessionListener implements HttpSessionListener {

    /**
     * 当前在线人数,仅作示例使用
     */
    private int onLineCount;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        onLineCount ++;
        log.info("sessionListener : create --> " + se.getSession().getId());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        log.info("sessionListener : destroy --> " + se.getSession().getId());
    }
}

MyController.java

@RestController
@RequestMapping("/geek")
@Slf4j
public class GeekController {


    @GetMapping("hello")
    public String sayHello(){
        log.info("controller invoked");
        return "hello everyone";
    }
}

就是以上代码,经过调用,发现,sessionCreated无论如何都不会被调用到,那么有两种情况,一种是Session没有被创建,一种是Session被创建了但是我们没有监听到。

接下来我们做了尝试:、

@GetMapping("hello")
public String sayHello(HttpServletRequest request){
	//此处断点
	log.info("controller invoked");
	return "hello everyone";
}

使用的工具为IntelliJ IDEA社区版本,然后我在SayHello方法第一行断点,然后无发起/hello请求,此时控制台没+有任何输出,然后当我添加了一个Variables

+ request.getSession()

debugger界面

此时控制台输入了

console界面

此时证明,我们已经监听到Session被创建并且sessionCreated()方法被调用了

上官方文档:

HttpSession Doc

红线表示:在客户端加入会话之前, isNew返回true。如果客户端选择不加入会话,getSession则会在每个请求上返回不同的会话,并且isNew将始终返回 true。 理解一下这句话的意思,getSession会返回不同的会话,我们的会话就代表Session,那么Session的创建时机,就是getSession方法里?

查阅了N多个资料,上面说的都是,Session的创建发生在request.getSesson中, 其中这篇文章讲的比较详细,大家可以去看https://blog.****.net/wowwilliam0/article/details/82736074

那么我们在Controller中调用一下尝试:

@GetMapping("hello")
    public String sayHello(HttpServletRequest request){
        request.getSession();
        log.info("controller invoked");
        return "hello everyone";
    }

确实被调用了,这个时候我们找到了为什么没有被调用的原因,那么依照个人经验,不会存在你使用了SessionListener但是却不会保存用户Session的情况,所以,如果是碰到了这个问题,那么你应该去主动保存用户端的Session,否则下次返回的仍然是个新对象,对你的程序没有任何帮助! other way, 提供另一种解决思路

@Configuration
@WebListener
@Slf4j
public class MyHttpRequestListener implements ServletRequestListener {
    
    private static int onLineCount = 0;

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        log.info("requestListener:  create--> " + request.getSession().getId());
        onLineCount ++;
    }

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        log.info("requestListener: destroy--> " + request.getSession().getId());
        onLineCount--;
    }
}

使用ServletRequestListener可以解决此问题,在这个监听器中,Session被床件可以正常监听到。