RedisHttpSession 的設計與實現

肖漢鬆發表於2016-07-30

前言

RedisHttpSession 是我的一個 Java 開源專案,通過將 Session 儲存在 Redis 中實現多伺服器間共享 Session,同時這一過程是完全透明的。主要用於支援 RESTfuls API。下面我將對其核心類進行分析,闡述它的設計以及實現細節。

RedisHttpSession

這個類實現了HttpSession介面,用於替換預設的HttpSession實現。RedisHttpSessionHttpSession的介面方法重寫了一遍,將HttpSession的屬性儲存到了 Redis 中。

每個RedisHttpSession都有一個 UUID 與之對應,該欄位加上session:字首作為儲存在 Redis 中的鍵值。例如:

同時,RedisHttpSession中的屬性是直接序列化成位元組陣列儲存在 Redis 中的,儲存在對應鍵中的雜湊表裡面。例如:

另外,Session 的自動過期是通過 Redis 設定鍵的過期時間實現的。

RedisHttpSessionProxy

RedisHttpSessionProxyRedisHttpSession的代理類,使用了 JDK 的動態代理。為什麼要引入代理?這是基於下面的考慮做出的設計。

  1. 由於 Session 儲存在 Redis 中,在執行每個RedisHttpSession的介面方法之前都需要檢查 Redis 連線是否可用。
  2. 訪問一個已經被登出的 Session 需要丟擲異常。
  3. 每次訪問 Session 需要重新整理過期時間和最後訪問時間。

基於上面的考慮,對於每個RedisHttpSession的介面方法,我們都需要進行重複的操作,因此使用動態代理對每個介面方法進行增強是最合適的。程式碼如下:

RedisHttpSessionFilter

RedisHttpSessionFilter作為過濾器,將請求和響應替換成RedisSessionRequestWrapperRedisSessionResponseWrapper,利用了裝飾器模式動態的給請求和響應進行增強:

  1. RedisSessionRequestWrapper:重寫了getSession,替換預設的HttpSession實現為RedisHttpSession
  2. RedisSessionResponseWrapper:在響應的頭部中加入x-auth-token欄位,作為 Session 的 ID。客戶端之後的請求都需要附帶該欄位,以便服務端識別對應的 Session。

總結

RedisHttpSession 利用 Filter 將請求的 Session 替換成 RedisHttpSession,在過濾階段偷樑換柱,在之後對 Session 的操作都無需關心其內部實現,整個過程都是透明的。

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

RedisHttpSession 的設計與實現 RedisHttpSession 的設計與實現

相關文章