springboot+spring-session
1. 實現背景
測試環境上部署了一個單機專案,專案的context-path為空,之後再經過nginx的轉發進行部署,專案可以正常進行登入等等一系列操作;生產環境跟測試環境程式碼完全相同,只是相關的專案配置包括nginx配置不同,專案可以正常啟動,但登入失敗。原本以為是nginx相關的配置有問題,導致調完登入介面,返回的cookie中攜帶的專案名不一致導致的。經過檢查發現登入介面返回的cookie中跟後續請求的cookie中的引數一致,所以跟配置無關。最後發現生產配置的專案是叢集模式,所以根本還是出現在session共享上面。
2.具體實現
這裡做的共享session用的是redis,所以要安裝redis並引入相關依賴;
<!--session--> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> <!-- redis依賴配置 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
其次application.yml中新增相關配置
spring: session: store-type: redis #是否將session存到redis none/redis timeout: 1800 # 配置session在redis中的過期時間 redis: flush-mode: immediate #儲存時重新整理,即響應結束後重新整理。預設是 on_save;immediate實時重新整理 namespace: smith:session #預設是spring:session redis: host:127.0.0.1 # Redis伺服器地址 database: 0 # Redis資料庫索引(預設為0) port: 6379 # Redis伺服器連線埠 password: # Redis伺服器連線密碼(預設為空) timeout: 3000ms # 連線超時時間
到這裡配置工作就完成了,啟動專案即可。
3. 錯誤資訊
org.springframework.boot.autoconfigure.session.SessionRepositoryUnavailableException: No session repository could be auto-configured, check your configuration (session store type is 'redis')
因為當store-type配置為redis的時候,redis是需要序列化的,所以我們還需要對restTemplate進行序列化,至此問題解決,專案可成功啟動。
@Configuration public class RedisConfiguration { /** * @param redisConnectionFactory:配置不同的客戶端,這裡注入的redis連線工廠不同: JedisConnectionFactory、LettuceConnectionFactory * @功能描述 :配置Redis序列化,原因如下: * (1) StringRedisTemplate的序列化方式為字串序列化, * RedisTemplate的序列化方式默為jdk序列化(實現Serializable介面) * (2) RedisTemplate的jdk序列化方式在Redis的客戶端中為亂碼,不方便檢視, * 因此一般修改RedisTemplate的序列化為方式為JSON方式【建議使用GenericJackson2JsonRedisSerializer】 */ @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); // key採用String的序列化方式 redisTemplate.setKeySerializer(StringRedisSerializer.UTF_8); // value序列化方式採用jackson redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // hash的key也採用String的序列化方式 redisTemplate.setHashKeySerializer(StringRedisSerializer.UTF_8); //hash的value序列化方式採用jackson redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; } }
4. 總結
當叢集模式時候,需要將登入相關資訊儲存在redis或其他資料庫中實現共享,也就是說sessionid儲存在客戶端的cookie裡面,然後將該sessionid作為key將session儲存在redis服務端。當部署很多個專案時候,因為session-namespace是預設值,所以可以修改namespace的值,把不同專案區分開。