根据网上配置了一个springsession整合redis作为session后,发现session获取失败,redis里面是有值。登录模块设置进去也能获取的到,但是其他的服务就获取不到。记录一下,跟着源码探寻为何失败
auth服务的配置

  1. 引入依赖
<dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
  1. 编写配置
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.0.94:8848
  application:
    name: eshop-auth
  thymeleaf:
    cache: false
  session:
    store-type: redis
  redis:
    host: 192.168.0.94
  1. 使用注解 @EnableRedisHttpSession
  2. 扩大cookie的域名
@Configuration
public class SessionConfig {
    @Bean
    public CookieSerializer cookieSerializer(){
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("gulimall.com");
        return cookieSerializer;
    }
}
  1. 登录成功后设置session
@PostMapping("/login")
    public String login(UserLoginVo loginVo, HttpSession session) {
        session.setAttribute("user","123");
        return "redirect:http://gulimall.com";
    }

其他模块

redis 数据库存储时设置失效时间如果失效redis会自动处理吗_抽象方法

探寻原理

  1. @EnableRedisHttpSession 注解下手,可以看到它引入了另一个配置 RedissonHttpSessionConfiguration
  2. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_spring_02

  3. RedissonHttpSessionConfiguration 又引入了一个 RedissonSessionRepository
  4. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_redis_03

  5. 并且 RedissonHttpSessionConfiguration 继承于 SpringHttpSessionConfiguration,这个类创建了一个filter
  6. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_redis_04

  7. 首先来分析 RedissonSessionRepository
    就是封装了一些对session的增删改查的操作
  8. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_java_05

  9. 再来看filter, 首先从刚才创建的 RedissonSessionRepository中获取放到内部
  10. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_spring_06

  11. 其中有一个方法
  12. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_spring_07

  13. 这个方法属于他的父类的抽象方法 OncePerRequestFilter
  14. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_spring_08

  15. dofilterinternal 方法内部把 request 和response 都包装了一遍传递给下一层
  16. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_抽象方法_09

  17. 这时候我们来看 springmvc 的 session 是怎么获得的。 直接用 session 和 request的 getsession是同样一个东西
  18. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_redis_10

  19. 所以我们来看看包装的request里面的getsession是怎么实现的
  20. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_java_11

  21. 由于我这次的问题是登录的session在主页找不到,所以一定是要有session 的,问题就出在 getRequestedSession 方法中
    这个sessionRepository 就是一开始注解中引入的类
  22. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_redis_12

  23. RedisSessionRepository 中对于session的操作
  24. redis 数据库存储时设置失效时间如果失效redis会自动处理吗_java_13

至此我在跟踪源码的过程中发现,在获取
S session = SessionRepositoryFilter.this.sessionRepository.findById(sessionId);
这个方法中返回的数据是null
仔细排查发现实现类变成了RedissonSessionRepository

因为这个模块中有使用redisson作为分布式锁,所以在使用注解的时候 @EnableRedisHttpSession 自动提示成了 @EnableRedissonHttpSession 导致出现的bug。如果看不懂源码,这个问题可能需要非常久的时间才能排查出来.