SpringBoot集群环境下使用Redis实现Session共享

95 篇文章 3 订阅
60 篇文章 2 订阅

环境:springboot2.3.9.RELEASE + Spring Session


引入相关依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>
</dependency>

应用配置文件

spring:
  redis:
    host: localhost
    port: 16379
    password: 111111
    database: 4
    lettuce:
      pool:
        maxActive: 8
        maxIdle: 100
        minIdle: 10
        maxWait: -1

使用Redis来存储Session必须配置
RedisConnectionFactoryBean。由于这里我们redis-starter自动为我们配置了该Bean。

启用Redis存储Session

@SpringBootApplication
@EnableRedisHttpSession
public class SpringBootHttpsessionApplication {

  public static void main(String[] args) {
    SpringApplication.run(SpringBootHttpsessionApplication.class, args);
  }

}

使用@EnableRedisHttpSession开启功能。

Controller设置Session

@RestController
@RequestMapping("/sessions")
public class SessionController {
	
  @Resource
  private HttpServletRequest request ;
	
  @GetMapping("/index")
  public Object index() {
    request.getSession().setAttribute("username", "asoklove") ;
    return "set session success" ;
  }
	
  @GetMapping("/get")
  public Object get() {
    System.out.println(request.getSession()) ;
    return request.getSession().getAttribute("username") ;
	}
	
}

调用接口

SpringBoot集群环境下使用Redis实现Session共享

 

session信息已经存储到了redis中;使用就是这么简单。

源码分析

进入@EnableRedisHttpSession类中

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(RedisHttpSessionConfiguration.class)
@Configuration(proxyBeanMethods = false)
public @interface EnableRedisHttpSession {
}  

@Import(RedisHttpSessionConfiguration.class)

进入
RedisHttpSessionConfiguration

@Autowired
	public void setRedisConnectionFactory(
			@SpringSessionRedisConnectionFactory ObjectProvider<RedisConnectionFactory> springSessionRedisConnectionFactory,
			ObjectProvider<RedisConnectionFactory> redisConnectionFactory) {
		RedisConnectionFactory redisConnectionFactoryToUse = springSessionRedisConnectionFactory.getIfAvailable();
		if (redisConnectionFactoryToUse == null) {
			redisConnectionFactoryToUse = redisConnectionFactory.getObject();
		}
		this.redisConnectionFactory = redisConnectionFactoryToUse;
	}

这里就是要自动装配RedisConnectionFactory。

@Bean
	public RedisIndexedSessionRepository sessionRepository() {
		RedisTemplate<Object, Object> redisTemplate = createRedisTemplate();
		RedisIndexedSessionRepository sessionRepository = new RedisIndexedSessionRepository(redisTemplate);
		// ...
		this.sessionRepositoryCustomizers
				.forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository));
		return sessionRepository;
	}

这里是配置SessionRepository Bean,该类是用来存储我们session的,通过类名
RedisIndexedSessionRepository也就知道了我们使用Redis进行存储。我们可以自定义SessionRepository来实现自己的Session存储类。

进入父类
SpringHttpSessionConfiguration中,这里配置了最核心的Filter

@Bean
	public <S extends Session> SessionRepositoryFilter<? extends Session> springSessionRepositoryFilter(
			SessionRepository<S> sessionRepository) {
		SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<>(sessionRepository);
		sessionRepositoryFilter.setHttpSessionIdResolver(this.httpSessionIdResolver);
		return sessionRepositoryFilter;
	}

该Filter Bean中配置了SessionRepository(这就是上面的
RedisIndexedSessionRepository);同时设置了session id解析器httpSessionIdResolver使用的默认的CookieHttpSessionIdResolver解析器,该类就是从header中的cookie中获取SESSION

SpringBoot集群环境下使用Redis实现Session共享

 

SpringBoot集群环境下使用Redis实现Session共享

 

第一次请求时,服务端会响应SESSION头信息

SpringBoot集群环境下使用Redis实现Session共享

 

请求时Cookie携带信息:

SpringBoot集群环境下使用Redis实现Session共享

 

这里我们也可以自定义HttpSessionIdResolver子类实现自己的解析器。比如可以读取Header中的其它信息来实现。

再接着说SessionRepositoryFilter过滤器,这个过滤的核心方法:

SpringBoot集群环境下使用Redis实现Session共享

 

这里吧HttpServletRequest对象进行了包装
SessionRepositoryRequestWrapper

这个类非常重要;我们在代码中使用request.getSession()方法它都重写了

 

 

查看getSession(boolean)方法

SpringBoot集群环境下使用Redis实现Session共享

 

HttpSession也被重写了,当我们在调用setAttribute时实际调用的是HttpSessionWrapper(父类)中的setAttribute,getAttribute方法。

在HttpSessionWrapper的父类中setAttribute方法

SpringBoot集群环境下使用Redis实现Session共享

 

关键代码this.session.setAttribute(name, value);

这里的this.session就是一开始配置的
RedisIndexedSessionRepository 对象。

再回到过滤器的doFilterInternal方法。执行finally代码

SpringBoot集群环境下使用Redis实现Session共享

 

SpringBoot集群环境下使用Redis实现Session共享

 

这里的sessionRepository就是上面的的Bean。

SpringBoot集群环境下使用Redis实现Session共享

 

SpringBoot集群环境下使用Redis实现Session共享

 

这里的saveDelta方法开始存储session信息到redis中。

完毕!!!

给个关注+转发呗谢谢

SpringBoot集群环境下使用Redis实现Session共享

 

SpringBoot集群环境下使用Redis实现Session共享

 

SpringBoot集群环境下使用Redis实现Session共享

 

SpringBoot集群环境下使用Redis实现Session共享

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值