spring-session整合redis原理 排查失效原因

根据网上配置了一个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";
    }

其他模块

探寻原理

  1. 从 @EnableRedisHttpSession 注解下手,可以看到它引入了另一个配置 RedissonHttpSessionConfiguration
  2. 而 RedissonHttpSessionConfiguration 又引入了一个 RedissonSessionRepository
  3. 并且 RedissonHttpSessionConfiguration 继承于 SpringHttpSessionConfiguration,这个类创建了一个filter
  4. 首先来分析 RedissonSessionRepository 就是封装了一些对session的增删改查的操作
  5. 再来看filter, 首先从刚才创建的 RedissonSessionRepository中获取放到内部
  6. 其中有一个方法
  7. 这个方法属于他的父类的抽象方法 OncePerRequestFilter
  8. dofilterinternal 方法内部把 request 和response 都包装了一遍传递给下一层
  9. 这时候我们来看 springmvc 的 session 是怎么获得的。 直接用 session 和 request的 getsession是同样一个东西
  10. 所以我们来看看包装的request里面的getsession是怎么实现的
  11. 由于我这次的问题是登录的session在主页找不到,所以一定是要有session 的,问题就出在 getRequestedSession 方法中 这个sessionRepository 就是一开始注解中引入的类
  12. RedisSessionRepository 中对于session的操作

至此我在跟踪源码的过程中发现,在获取 S session = SessionRepositoryFilter.this.sessionRepository.findById(sessionId); 这个方法中返回的数据是null 仔细排查发现实现类变成了RedissonSessionRepository 因为这个模块中有使用redisson作为分布式锁,所以在使用注解的时候 @EnableRedisHttpSession 自动提示成了 @EnableRedissonHttpSession 导致出现的bug。如果看不懂源码,这个问题可能需要非常久的时间才能排查出来.

经验分享 程序员 微信小程序 职场和发展