1、session原理:
jsessionid
相当于银行卡,存在服务器的session
相当于存储的现金,每次通过jsessionid
取出保存的数据。
问题:但是正常情况下session
不可跨域,它有自己的作用范围。
2、问题:
1)同一个服务复制多份,部署到不同服务器上,session不能同步的问题?
2)同一服务器上,不同的服务,session不能共享的问题?
3、解决方案:
1) session复制:
2) 客户端存储:
3) hash一致性
4) 统一存储:
以上都仅仅是一种思路,现在引出今天的主角-----SpringSession
4、SpringSession整合redis:
通过SpringSession
修改session
的作用域。
5、具体使用:
1)环境搭建:
参考文档:Spring Session - Spring Boot :: Spring Session
导入依赖:
<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: 192.168.56.102
session:
store-type: redis
添加注解:@EnableRedisHttpSession
@EnableRedisHttpSession
public class GulimallAuthServerApplication {
2)自定义配置
-
由于默认使用jdk进行序列化,通过导入
RedisSerializer
修改为json序列化 -
并且通过修改
CookieSerializer
扩大session
的作用域至父域`,例如:gulimall.com`**
@Configuration
public class GulimallSessionConfig {
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("GULISESSIONID");
serializer.setDomainName("gulimall.com");
return serializer;
}
}
3)SpringSession核心原理 - 装饰者模式:
-
原生的获取
session
时是通过HttpServletRequest
获取的。 -
这里对request进行包装,并且重写了包装request的
getSession()
方法。 -
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository); //对原生的request、response进行包装 SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper( request, response, this.servletContext); SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper( wrappedRequest, response); try { filterChain.doFilter(wrappedRequest, wrappedResponse); // 包装后的对象应用到了我们后面的整个执行链 } finally { wrappedRequest.commitSession(); } }