Session与Redis的结合,spring-session-
现在越来越多的项目使用微服务分布式,那么对于分布式:
session 该如何共享呢?
spring-session-data-redis 框架就是来解决这个问题的。
一、简单使用;
1. 使用 IDEA 的 Spring Starter Project 新建一个带web的测试项目,打开pom文件,加入两个依赖:
<!-- 引入 session与redis的集成 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<!-- redis连接配置 -->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
2. 创建测试类 IndexController;
package com.example.demo.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 分布式测试session共享示例
* @author 程就人生
* @Date 2022-01-09
*/
@RestController
public class IndexController {
/**
* 设置session
* @param request
* @return
*/
@GetMapping("/set")
public Object Index(HttpServletRequest request){
request.getSession().setAttribute("userUid", "111111");
return request.getSession().getAttribute("userUid");
}
/**
* 获取session
* @param request
* @return
*/
@GetMapping("/get")
public Object Index1(HttpServletRequest request){
return request.getSession().getAttribute("userUid");
}
}
3.测试session共享
分别以端口8080、8081启动该项目;启动后,通过一个浏览器打开两个浏览器窗口;
一个输入地址:http://localhost:8080/set
另一个输入地址:http://localhost:8081/get
4.查看redis里session的存储结构;
从redis的客户端,可以看到关于session的详细信息:
就是这么简单地实现了分布式session共享~!
当然肯定有朋友会问:
如果想更改session的过期日期,怎么改?
如果想更改session存储在redis里的前缀,怎么改?
二、关键注解 @EnableRedisHttpSession 分析;
@EnableRedisHttpSession 源码查看;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(RedisHttpSessionConfiguration.class)
@Configuration(proxyBeanMethods = false)
public @interface EnableRedisHttpSession {
/**
* Session默认过期时间,单位为秒,默认30分钟
*/
int maxInactiveIntervalInSeconds() default MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
/**
* Defines a unique namespace for keys.
* 配置session key的命名前缀,默认是spring
*/
String redisNamespace() default RedisIndexedSessionRepository.DEFAULT_NAMESPACE;
/**
* Flush mode for the Redis sessions.
* In a web environment this happens just before the HTTP response is committed.
* Session are immediately written to the Redis instance.
* 配置刷新Redis中Session的方式,默认是ON_SAVE模式,只有当Response提交后才会将Session提交到Redis
* 也可以配置成IMMEDIATE模式,所有对Session的更改会立即更新到Redis
*/
RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE;
/**
* 同 redisFlushMode
*/
FlushMode flushMode() default FlushMode.ON_SAVE;
/**
* The cron expression for expired session cleanup job.
* By default runs every minute. "0 * * * * *"
* 清理过期Session的定时任务默认一分钟一次
*/
String cleanupCron() default RedisHttpSessionConfiguration.DEFAULT_CLEANUP_CRON;
/**
* 只有在更改的时候才进行保存;
*/
SaveMode saveMode() default SaveMode.ON_SET_ATTRIBUTE;
}
源码分析:如果都使用默认配置,那么该注解可加可不加;
如果想设置session过期时间,那么就可以在该注解上做调整;
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
/**
* @EnableRedisHttpSession 注解说明
* @author 程就人生
* @Date 2022-01-09
*/
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS * 2, //1小时有效期
redisNamespace = "myUser", // 前缀为myUser
flushMode = FlushMode.IMMEDIATE // 立即生效
)
@SpringBootApplication
public class SpringSessionRedisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringSessionRedisApplication.class, args);
}
}
修改过了,测试一下,从下图中可以看到,redis的命名和过期时间都发生了改变;
测试结果
原理分析:该注解导入了 RedisHttpSessionConfiguration类,该类被注解了@Configuration,容器一启动里面的bean就会被加载:
RedisHttpSessionConfiguration类又继承自 SpringHttpSessionConfiguration,在该类中通过 SessionRepositoryFilter 类 对所有的session进行了拦截:
SessionRepositoryFilter 类,该类继承自 SessionRepositoryFilter :
对所有的请求进行了拦截:
最后总结
主要的核心类:
@EnableRedisHttpSession,配置注解,需要调整时再覆盖默认配置;
RedisHttpSessionConfiguration,配置类,自动配置,开箱即用;
SessionRepositoryFilter,拦截器,对HttpServletRequest、Response的拦截;
RedisOperationsSessionRepository,在Redis中增删改查Session的功能;
SessionRepositoryRequestWrapper,Request的包装类;
SessionRepositoryResponseWrapper,Response的包装类。
参考文档:
https://docs.spring.io/spring-session/reference/guides/java-redis.html
https://blog.csdn.net/qq_27088383/article/details/107767000