spring-boot+spring-session整合

菜鳥快飛發表於2018-01-10

在這個微服務,分散式的時代,很多傳統的實現方案變的不再那麼適用,比如傳統的web服務將session放在記憶體中的情況,當web服務做水平擴充套件部署的時候,session共享就成了需要處理的問題。目前有很多成熟的技術可供我們選擇,下面簡單介紹最近用到的spring-boot+spring-session實現session共享的方案。

spring-boot整合spring-session非常簡單,因為spring-boot為我們完成了非常多的工作。具體整合步驟如下:

一、工程繼承spring-boot-starter-parent

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.2.RELEASE</version>
</parent>

這樣做的好處是我們接下來引入其他依賴包可以不需要考慮版本問題,推薦這樣做,避免自己引入不當導致的相容性問題。

二、引入spring-session依賴包

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session</artifactId>
</dependency>

引入之後,我們要確定我們要將session持久化到哪種介質中了。因為分散式session可以持久化到資料庫、redis、nosql等中,根據儲存方式不同,需要引入不同的jar包和做不同的操作。我們以redis儲存為例。

三、引入redis依賴包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

由於我們使用了spring-boot,所以我們只需要引入spring-boot-starter-data-redis依賴即可,這樣我們可以很好的利用spring-boot開箱即用以及非常方便的配置優勢。

四、基礎配置

由於我們引入了redis,這樣我們需要在application.properties或者application.yml檔案中配置redis連線,使用spring-boot我們可以很方便配置單點redis,哨兵模式,叢集模式等,簡單起見我們配置一個單點模式的redis連線並採用連線池

spring.redis.port=6379
spring.redis.host=127.0.0.1
spring.redis.password=******
spring.redis.pool.max-active=100
spring.redis.pool.max-idle=5
spring.redis.pool.max-wait=60000

完成以上步驟之後,我們只需要告訴spring開啟redis方式的session儲存即可,這裡有兩種方式可以實現

  • 方式1、在配置檔案中新增一行配置
spring.session.store-type=redis
  • 方式2、在程式啟動類上新增註解
@EnableRedisHttpSession

兩種方式都可以完成開啟spring-session的redis儲存,是不是非常簡單。因為spring-boot的特性,以前很多需要在xml中配置的都可以輕鬆幫我們搞定。

擴充套件

雖然我們實現了redis方式儲存的分散式session,但是在實際場景中可能還有一些需要優化的地方。

一、修改cookies中sessionId的名字

二、修改session存放在redis中的名稱空間

三、修改session超時時間

為什麼要這樣做呢,如果我們有兩套不同系統A和B,cookies中session名稱相同會導致同一個瀏覽器登入兩個系統會造成相互的干擾,例如兩個系統中我們存放在session中的使用者資訊的鍵值為user。預設情況下cookies中的session名稱為JSESSIONID。當我們登入A系統後,在同一個瀏覽器下開啟B系統,B系統B系統拿到的user實際上並非自己系統的user物件,這樣會造成系統異常;而如果我們A、B系統存放使用者資訊的鍵值設定為不相同,例如userA和userB,當我們登入A系統後在登入B系統,我們開啟瀏覽器除錯模式方向兩個系統只有一個sessionId,因為我們沒有對二者的session名稱以及儲存的名稱空間做區分,程式會認為就是自己可用的session。當我們推出B系統,登出session後。發現B系統的session也失效了,因為在redis中JSESSIONID對應的資料已經被設定過期了。

同理,如果兩個系統想要不同的session過期時間,也存在相同的問題。所以,建議不同系統,session名稱以及儲存的名稱空間設定為不同,當然相同系統的水平擴充套件例項的情況除外

針對名稱空間,我們可以在配置檔案上新增配置解決

spring.session.redis.namespace=xxxx

如果是註解方式的也可以在註解上設定

@EnableRedisHttpSession(redisNamespace="xxxx")

這樣我們檢視redis中就可以看到sping-session儲存的key就變成了我們設定的值。

針對超時時間,註解方式提供了響應的設定

@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)

但是配置檔案方式並沒有提供響應的直接設定。
我們可以採用javaconfig方式自定義策略來設定超時以及設定cookies名稱,如下我們設定超時時間是1800秒,cookies名為MYSESSIONID

@Configuration 

@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 180,redisNamespace="com.lywcts")

public class HttpSessionConfig { 

@Bean

public CookieHttpSessionStrategy cookieHttpSessionStrategy(){

    CookieHttpSessionStrategy strategy=new CookieHttpSessionStrategy();

    DefaultCookieSerializer cookieSerializer=new DefaultCookieSerializer();

    cookieSerializer.setCookieName("MYSESSIONID");//cookies名稱

    cookieSerializer.setCookieMaxAge(1800);//過期時間(秒)

    strategy.setCookieSerializer(cookieSerializer);

    return strategy;

}

}

總結

通過以上步驟,我們就完成了分散式session的整合。相對於傳統的記憶體方式,分散式session實現能夠更方便水平擴充套件以及系統維護。對於不想立馬更改系統採用token方式來進行驗證的系統來說是一種簡便、快速、低成本的一種實現思路。

轉自:https://yq.aliyun.com/articles/182676?utm_content=m_29523

相關文章