1. 程式人生 > >SpringBoot中結合SpringSession的原理

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原理的介紹,歡迎各位大佬指點