1. 功能描述
提供开箱即用的集中式用户session管理, 从而不需要依赖web应用容器.
2. 使用
2.1. 引入依赖
<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>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
</dependency>
2.2. 添加session配置
spring:
application:
name: session-demo
session:
store-type: redis
logging:
level:
org.springframework.session: debug
2.3. 设置token位置为header(Optional)
@Configuration
public class SessionConfiguration {
@Bean
public HttpSessionIdResolver sessionIdResolver() {
return HeaderHttpSessionIdResolver.xAuthToken();
}
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
}
2.4. 写个接口
@RestController
public class DemoController {
@GetMapping("/")
public String index(@Value("${spring.application.name}") String name, HttpSession session) {
return name;
}
}
2.5. 测试一下
@SpringBootTest(classes = SessionDemoApplication.class)
@AutoConfigureMockMvc
class DemoControllerTest {
@Autowired
private MockMvc mockMvc;
@Value("${spring.application.name}")
private String applicationName;
@Test
void testSessionHeader() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/"))
.andDo(MockMvcResultHandlers.log())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string(applicationName))
.andExpect(MockMvcResultMatchers.header().exists("X-Auth-Token"))
.andReturn();
}
}
3. 核心类
3.1. Session
标识同一个session(user).
-
MapSession: 一些基本的属性:
id/originalId/attrs/creationTime/lastAccessedTime
. -
RedisSession: session attribute修改时内部会同步修改redis中的值.
3.2. SessionRepository
具体操作session.
-
MapSessionRepository: 在内存中维护一个
Map
管理session. -
FindByIndexNameSessionRepository: 新增根据用户名或者指定key查询session的接口.
-
RedisOperationsSessionRepository: 用
RedisTemplate
管理session.
3.3. SessionRepositoryRequestWrapper
包装 HttpServletRequest
, 覆盖 getSession
等方法.
3.4. SessionRepositoryResponseWrapper
包装 HttpServletResponse
, 调用部分方法时同步session到Redis中.
3.5. SessionRepositoryFilter
每次请求将 HttpServletRequest
和 HttpServletResponse
分别包装成 SessionRepositoryRequestWrapper
和 SessionRepositoryResponseWrapper
.
4. 启动流程
-
spring.factories
中存在org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
,自动引入SessionAutoConfiguration
. -
SessionAutoConfiguration.ServletSessionConfiguration.ServletSessionRepositoryConfiguration
根据spring.session.store-type
和WebApplicationType
引入不同的SessionConfiguration类, 通常为RedisSessionConfiguration
. -
SpringBootRedisHttpSessionConfiguration
配置类装载bean:-
RedisOperationsSessionRepository
-
SessionRepositoryFilter
-
SessionEventHttpSessionListenerAdapter
-
RedisMessageListenerContainer
-
EnableRedisKeyspaceNotificationsInitializer
-