在傳統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,裏面實現都很簡單,這裏就不說了。