SpringBoot中結合SpringSession的原理
這篇文章主要講解的是在SpringBoot專案中,SpringSession的執行原理,同時可以幫助大家更好的對SpringSession進行自定義使用。
一、SpringSession的使用:
1.匯入依賴:
我使用的是maven專案,而專案中我們使用的是redis儲存session,所以匯入的依賴為:
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> <version>1.3.1.RELEASE</version> </dependency>
因為spring-session-data-redis裡自動引入了spring-data-redis依賴,所以只需要引入這一個就可以連線到redis。
如果用的其他資料來源,引入相對應的依賴即可。
2.開啟springsession
@SpringBootApplication @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800) public class RedisSessionApplication{ public static void main(String[] args) { SpringApplication.run(RedisSessionApplication.class,args); } }
其中maxInactiveIntervalInSeconds設定的是session的過期時間,這裡設定的是30分鐘。
另外有的人可能會擔心session的清除問題,經過測試springsession的過期時間策略是框架自己實現的,並沒有用到redis本身的儲存過期時間,當session過期後springsession會呼叫redis的刪除方法將對應的session刪除。
3.配置application.yml檔案
其實在這裡,如果只是做demo的話是不用配置的,當專案啟動的時候他會預設訪問本地的6379埠。當然需要配置redis叢集或者哨兵模式,或者修改預設配置,則需要詳細配置。這裡不再闡述,有興趣的朋友可以參考我寫的關於配置redis的文章。
以上準備工作就算完成了,啟動專案即可。
二、SpringSession的執行原理
1.配置載入
跟本文相關的主要兩個配置類RedisHttpSessionConfiguration和SpringHttpSessionConfiguration
(1)以下是RedisHttpSessionConfiguration類中的一些主要配置:
@Bean
public RedisOperationsSessionRepository sessionRepository(
@Qualifier("sessionRedisTemplate") RedisOperations<Object, Object> sessionRedisTemplate,
ApplicationEventPublisher applicationEventPublisher) {
RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(
sessionRedisTemplate);
sessionRepository.setApplicationEventPublisher(applicationEventPublisher);
sessionRepository
.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
if (this.defaultRedisSerializer != null) {
sessionRepository.setDefaultSerializer(this.defaultRedisSerializer);
}
String redisNamespace = getRedisNamespace();
if (StringUtils.hasText(redisNamespace)) {
sessionRepository.setRedisKeyNamespace(redisNamespace);
}
sessionRepository.setRedisFlushMode(this.redisFlushMode);
return sessionRepository;
}
主要就是將操縱redis的redisTemplate放入sessionRepository中,而sessionRepository中統一規定了獲取session的方法名。即可通過sessionRepository從redis裡獲取session。
(2)以下是SpringHttpSessionConfiguration中的一些主要配置:
@Bean
public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(
SessionRepository<S> sessionRepository) {
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<S>(
sessionRepository);
sessionRepositoryFilter.setServletContext(this.servletContext);
if (this.httpSessionStrategy instanceof MultiHttpSessionStrategy) {
sessionRepositoryFilter.setHttpSessionStrategy(
(MultiHttpSessionStrategy) this.httpSessionStrategy);
}
else {
sessionRepositoryFilter.setHttpSessionStrategy(this.httpSessionStrategy);
}
return sessionRepositoryFilter;
}
這裡生成了一個SessionRepositoryFilter過濾器,並將上一個配置類中的sessionRepository放入到這個過濾器中。所以這個過濾器就是替換伺服器session的關鍵。
2.執行過濾器
當有http請求傳送過來後,將會執行上文中的過濾器。
主要執行的方法:
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(
request, response, this.servletContext);
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(
wrappedRequest, response);
HttpServletRequest strategyRequest = this.httpSessionStrategy
.wrapRequest(wrappedRequest, wrappedResponse);
HttpServletResponse strategyResponse = this.httpSessionStrategy
.wrapResponse(wrappedRequest, wrappedResponse);
try {
filterChain.doFilter(strategyRequest, strategyResponse);
}
finally {
wrappedRequest.commitSession();
}
}
這個doFilterInternal方法重寫的是OncePerRequestFilter抽象類的方法,而OncePerRequestFilter實現的是Filter介面,在doFilter方法中會呼叫doFilterInternal。
這裡先是將sessionRepository放入到了request的attribute中,然後又用框架中的類SessionRepositoryRequestWrapper對request進行了封裝。這個類裡有利用sessionRepository建立,獲取,刪除session的方法。
同時對response也進行了封裝,之後再講封裝過得request和response傳給下一個過濾器。
至此session的替換就完成了。
3.其他的設定
在配置類裡有很多其他的方法,可以讓使用者自定義一些策略,比如cookie的序列化策略,session生成的策略等等。只需要手動寫一個配置類,建立對應的bean即可,下面是其中一部分可自定的部分。
@Autowired(required = false)
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
@Autowired(required = false)
public void setCookieSerializer(CookieSerializer cookieSerializer) {
this.cookieSerializer = cookieSerializer;
}
@Autowired(required = false)
public void setHttpSessionStrategy(HttpSessionStrategy httpSessionStrategy) {
this.httpSessionStrategy = httpSessionStrategy;
}
@Autowired(required = false)
public void setHttpSessionListeners(List<HttpSessionListener> listeners) {
this.httpSessionListeners = listeners;
}
}
以上就是關於springsession原理的介紹,歡迎各位大佬指點