官方介绍
Spring Session 提供了一个 API 和实现,用于管理用户的会话信息,同时使其在不依赖于特定于应用程序容器的解决方案的情况下,可以轻松地支持集群会话。它还提供了透明的集成:
HttpSession
允许以中立的方式替换应用程序容器(即 Tomcat)中的HttpSession,并支持在 Headers 中提供会话 ID 以与 RESTful API 一起使用。WebSocket
能够在接收 WebSocket 消息时使HttpSession保持活动状态WebSession
允许以与应用程序容器无关的方式替换 Spring WebFlux 的WebSession。
Spring Session 支持多种会话存储方式,本次讲解我们使用 Redis 实现
Spring Session Data Redis
使用 Redis 实现 Spring Session 会话共享
pom.xml 文件
主要引入spring-session-data-redis
包和spring-boot-starter-data-redis
,同时为了演示方便,还引入了web
、fastjson
、logging
<dependencies>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
</dependencies>
application.yml 配置
spring:
session:
store-type: redis
timeout: 8H
redis:
namespace: spring:session
redis:
host: localhost
port: 6379
database: 0
spring.session.store-type
用于指定 Session 的存储类型,我们选择 redis,有了此配置会自动将 Http Session 替换成 Spring Sessionspring.session.timeout
设置会话超时时间spring.session.redis.namespace
用于指定 Session 在 Redis 中的命名空间
redis序列化方式配置
默认序列化方式存入的数据会出现乱码情况,而官方为我们提供了多种序列化方式,在这里我们使用 GenericFastJsonRedisSerializer
。
其他方式请参阅源码RedisSerializer
接口的实现。
@Configuration
public class RedisConfig {
@Bean("springSessionDefaultRedisSerializer")
public RedisSerializer<Object> redisSerializer() {
return new GenericFastJsonRedisSerializer();
}
}
测试
有了上边的配置,就已经实现了 Redis Session 共享了,我们简单来做个测试
User 实体类
public class User implements Serializable {
private Long id;
private String username;
private String password;
// get/set...
}
UserService
只有一个方法getUserByUsernameAndPassword
,用于模拟从数据库取用户信息
@Service
public class UserService {
public User getUserByUsernameAndPassword(String username, String password) {
User user = new User();
user.setUsername(username);
user.setPassword(password);
user.setId(1L);
return user;
}
}
UserController
只有两个方法login
和getData
简单测试
@RestController
@RequestMapping("/user")
public class UserController {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Resource
private UserService userService;
@PostMapping("/login")
public String login(String username, String password, HttpSession session) {
User user = userService.getUserByUsernameAndPassword(username, password);
String userJson = JSONObject.toJSONString(user);
session.setAttribute("user", userJson);
log.info("sessionId: {}, user: {}", session.getId(), userJson);
return JSONObject.toJSONString(user);
}
@GetMapping("/data")
public String getData(HttpSession session) {
Object user = session.getAttribute("user");
String userJson = JSONObject.toJSONString(user);
log.info("sessionId: {}, user: {}", session.getId(), userJson);
return userJson;
}
}
使用 Postman 分别调用上边两个方法:
login
将用户信息取出并存入 Session,此时 Spring Session 会将 Session 信息存储 Redis 中,可以查看 Redis 中的信息
getData
调用此方法,发现用户信息可以取出