在传统web应用中,session都是交给容器管理,但是对于分布式或是集群,如果交给web容器管理的话,自然是行不通的,除非是web容器共享session,但是这样做需要入侵web容器,提高问题的复杂度,并且集群机器之间要相互耦合。因此,springsession来了。
springSession将session从web容器中剥离出来,单独存在服务器中。目前支持redis、database、mogonDB等。session管理责任委托给springSession承担,当request进入web容器中时,所需的session都从springsession中获取。
接下来实现一下:
<!-- springboot - Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
spring.redis.database=1
spring.redis.host=127.0.0.1
spring.redis.port=6379
# 连接池最大连接数
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=3000
spring.session.store-type=redis
spring.session.redis.namespace=haozi
@GetMapping(value = "test")
public String test(HttpServletRequest request){
HttpSession session = request.getSession();
User user = new User(1 , "haozi" , 18);
session.setAttribute(session.getId() , user);
return port + session.getId();
}
@GetMapping(value = "gettest")
public String getTest(HttpServletRequest request){
HttpSession session = request.getSession();
String haozi = (String) session.getAttribute(session.getId());
return haozi;
}
在redis中通过monitor监听看下运行数据:
publish是发布订阅,是springsession为了后面删除用户信息用的。
再看下存的内容:
通过桌面程序可以看到结构:
其中expires没有value,是用来做倒计时用的,倒计时结束就会把session删掉。再看下前端响应参数:
会把存入的token存入cookie,如果想改“session”,需要加个bean
@Configuration
public class SpringSessionBeanConfiguration {
//Cookie配置
@Bean
public CookieSerializer cookieSerializer(){
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
cookieSerializer.setCookieName("user_session");//sessionId名称
return cookieSerializer;
}
//HttpSessionId配置
@Bean
public HttpSessionIdResolver httpSessionIdResolver(){
CookieHttpSessionIdResolver cookieHttpSessionIdResolver = new CookieHttpSessionIdResolver();
cookieHttpSessionIdResolver.setCookieSerializer(cookieSerializer());
return cookieHttpSessionIdResolver;
}
}
再运行就变成自定义的了
具体源码是在DefaultCookieSerializer中,可以自己去看看。
接下来总体看下源码:
首先AbstractHttpSessionApplicationInitializer#onstartup
启动后会在这个里面添加监听、过滤器,接下来进insertSessionRepositoryFilter看一下,
其中,DEFAULT_FILTER_NAME就是springSessionRepositoryFilter,将配置的filter做代理,然后注册,那接下来进代理类看下doFilter:
通过invokeDelegate就来到了springsession下的OncePerRequestFilter:
如果是请求第一次进filter,就会进doFilterInternal方法,
SessionRepositoryRequestWrapper和SessionRepositoryResponseWrapper封装了很多方法,看看SessionRepositoryRequestWrapper,里面有很多方法,对session进行了一些列的封装。
关于cookie的sessionid的封装,可以看CookieHttpSessionStrategy,里面实现都很简单,这里就不说了。