背景:在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()
此时控制台输入了
此时证明,我们已经监听到Session被创建并且sessionCreated()方法被调用了
上官方文档:
红线表示:在客户端加入会话之前, isNew返回true。如果客户端选择不加入会话,getSession则会在每个请求上返回不同的会话,并且isNew将始终返回 true。 理解一下这句话的意思,getSession会返回不同的会话,我们的会话就代表Session,那么Session的创建时机,就是getSession方法里?
查阅了N多个资料,上面说的都是,Session的创建发生在request.getSesson中, 其中这篇文章讲的比较详细,大家可以去看https://blog.csdn.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被床件可以正常监听到。
原创,转载请注明出处,谢谢