根本原因是未引入spring-session-data-redis依赖或版本不匹配,仅靠spring-boot-starter-data-redis无法触发session持久化;必须显式引入对应boot版本的spring-session-data-redis,并配置spring.session.store-type=redis且确保@enableredishttpsession正确生效。

spring-session-data-redis 依赖缺失或版本不匹配
根本原因不是配置写错了,而是压根没让 Spring Session 知道 Redis 的存在。只加 spring-boot-starter-data-redis 不够——它只提供连接能力,不触发 session 持久化逻辑。
必须显式引入 spring-session-data-redis,且版本需与 Spring Boot 对齐:
- Spring Boot 2.4+:直接用 BOM 管理的
org.springframework.session:spring-session-data-redis,无需指定版本 - Spring Boot 2.1.x:需匹配
spring-session-data-redis2.1.x 版本,否则自动配置不生效 - 绝对不要混用老版
spring-session(无data-redis后缀)或已废弃的spring-boot-starter-redis
验证方式:redis-cli keys spring:session:* 应返回空;但若连这个前缀都查不到,说明 session 根本没走 Redis,还在内存里。
spring.session.store-type=redis 未生效或被覆盖
Spring Boot 2.0+ 默认启用自动配置,但前提是 spring.session.store-type 不能是 none,也不能被其他配置意外覆盖。
常见干扰点:
- application.yml 中写了
spring.session.store-type: redis,但 profile 激活了另一个配置文件,其中该值为none或未定义 - 代码中存在
@EnableRedisHttpSession注解,但同时又在配置里设了spring.session.store-type=none,后者会强制禁用 - 使用了自定义
ServletWebServerFactory或手动注册Filter,绕过了 Spring Session 的SessionRepositoryFilter自动注册
建议始终显式配置并检查生效环境:spring.session.store-type=redis,避免 fallback 到内存 session。
@EnableRedisHttpSession 缺失或位置错误
虽然自动配置能工作,但缺 @EnableRedisHttpSession 是最常被忽略的硬性开关。它不只是“声明意图”,而是触发关键 Bean 注册(如 RedisOperationsSessionRepository)的入口。
注意两点:
- 注解必须加在某个
@Configuration类上,且该类需被 Spring 扫描到(不能放在test目录或未被@ComponentScan覆盖的包下) - 如果项目用了 WebFlux(而非 WebMvc),要用
@EnableRedisWebSession,否则完全不生效 - Spring Boot 3.x + Jakarta EE 9+ 环境下,确保 classpath 有
jakarta.servlet.Filter,否则注解无法注册 filter 链
没有它,HttpServletRequest.getSession() 返回的仍是 StandardSession,和 Redis 无关。
Redis 连接成功但 session 写入失败(静默丢弃)
现象是应用启动无报错、Redis 可 ping 通、key 前缀也对,但就是没数据。大概率是序列化器冲突或 session 命名空间被覆盖。
排查重点:
-
spring.redis.namespace配置是否被误写成spring.session.redis.namespace?正确项是spring.session.redis.namespace,但旧文档常写错,导致 key 写到默认spring:session:外的路径 - 是否混用了
StringRedisTemplate和RedisTemplate?前者默认StringRedisSerializer,后者默认JdkSerializationRedisSerializer,session 写入必须用后者兼容的序列化器 - Redis 实例是否启用了 ACL 且当前用户无
set权限?Lettuce 日志里会出现NOAUTH或NOPERM,但 Spring Session 默认吞掉这类异常,不抛出
最有效的验证动作:在 controller 里手动调用 session.setAttribute("test", "ok") 后立刻用 redis-cli monitor 观察是否有 SET 命令发出——没有,说明拦截链断了;有但失败,就看 Redis 服务端日志。
真正卡住的地方往往不在配置语法,而在依赖链的隐式约束和自动配置的触发边界。比如 spring-session-data-redis 在 classpath 上,但被 Maven optional=true 标记的模块排除了;或者 Spring Boot 的条件化配置因为某个多余的 starter 被跳过。这些细节不打印日志、不报错,只安静地让 session 留在内存里。











