Spring MVC中HttpSessionListener失效问题(Spring JDBC Session+Security)
解决Spring JDBC Session下HttpSessionListener不生效的问题
你遇到的问题其实是Spring Session(JDBC版)的核心特性导致的:Spring Session会替换Servlet容器的原生HttpSession实现,所以传统的HttpSessionListener根本不会被容器触发——因为实际使用的已经不是容器管理的会话了。
接下来给你两种可行的解决方案,都是基于Spring Session自身的事件机制来实现会话监听:
方案1:使用Spring Session的事件发布器+ApplicationListener
Spring Session提供了SessionEventPublisher,它会把Spring Session内部的会话事件转化为Spring应用上下文的事件,我们只需要实现ApplicationListener来监听这些事件即可。
步骤1:配置SessionEventPublisher Bean
在你的Spring配置类中添加这个Bean:
@Bean public SessionEventPublisher sessionEventPublisher() { return new SessionEventPublisher(); }
步骤2:实现自定义的事件监听器
把原来的HttpSessionListener改成实现ApplicationListener<AbstractSessionEvent>,监听会话创建和销毁事件:
@Component public class CustomSessionListener implements ApplicationListener<AbstractSessionEvent> { @Override public void onApplicationEvent(AbstractSessionEvent event) { if (event instanceof SessionCreatedEvent) { Session session = ((SessionCreatedEvent) event).getSession(); // 这里写你的会话创建逻辑,比如记录日志、初始化会话数据 System.out.println("会话已创建,ID:" + session.getId()); } else if (event instanceof SessionDestroyedEvent) { Session session = ((SessionDestroyedEvent) event).getSession(); // 这里写你的会话销毁逻辑,比如清理关联资源、记录用户登出日志 System.out.println("会话已销毁,ID:" + session.getId()); } } }
方案2:定制SessionRepository,添加SessionRepositoryListener
如果你需要更贴近Spring Session底层的监听(比如会话更新、删除的实时触发),可以通过SessionRepositoryCustomizer来给JdbcIndexedSessionRepository添加自定义监听器:
@Component public class CustomSessionRepoCustomizer implements SessionRepositoryCustomizer<JdbcIndexedSessionRepository> { @Override public void customize(JdbcIndexedSessionRepository sessionRepository) { sessionRepository.addSessionRepositoryListener(new SessionRepositoryListener<Session>() { @Override public void onCreated(Session session) { // 会话创建时触发 } @Override public void onUpdated(Session session) { // 会话属性更新时触发(比如用户修改了会话中的数据) } @Override public void onDeleted(Session session) { // 会话被删除时触发(对应登出、会话过期) } }); } }
额外注意点
- 过滤器顺序:你web.xml里的
springSessionRepositoryFilter已经在springSecurityFilterChain之前了,这个是正确的——Spring Session的过滤器必须先拦截请求,才能替换掉原生的HttpSession实现,确保Spring Security使用的是Spring Session管理的会话。 - 登出事件触发:Spring Security登出时是通过Spring Session的API删除会话,所以只会触发Spring Session的
SessionDestroyedEvent或者onDeleted方法,不会触发Servlet容器的HttpSessionDestroyedEvent,这也是你原来的监听器没反应的核心原因。
内容的提问来源于stack exchange,提问作者MRS2710
相关产品推荐
相关产品推荐

