HTTP 本質無狀態,Session 是伺服器端為客戶端創建的「有狀態會話」抽象。理解其生命週期、存儲模式、集群挑戰與安全屬性,是構建健壯 Web 應用的必修課。
| 方法 | 用途 | 注意事項 | ||
|---|---|---|---|---|
| getId() | 獲取 Session ID | 僅供日誌/調試,不可作為業務鍵 | ||
| setAttribute(name, value) | 存儲對象 | value 必須可序列化 (集群/持久化需求) | ||
| getAttribute(name) | 讀取對象 | 返回 Object,需類型轉換 | ||
| removeAttribute(name) | 移除屬性 | |||
| isNew() | 判斷是否新創建 | 客戶端未攜帶有效 ID 時為 true | ||
| getCreationTime() / getLastAccessedTime() | 生命週期統計 | 長整型毫秒時間戳 | ||
| setMaxInactiveInterval(seconds) | 設置超時時間 | 覆蓋 web.xml 全局配置,負值 = 永不過期 | ||
| invalidate() | 強制銷毀 | 解綁所有屬性,觸發 HttpSessionBindingListener |
| 方案 | 原理 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| 文件系統持久化 | 定期序列化 Session 到磁盤 | 實現簡單、重啟恢復 | I/O 瓶頸、不支持集群 | 單機、低併發 |
| 數據庫持久化 (JDBC Store) | Session 表 (session_id, data, expiry) | 集群共享、ACID 保障 | 寫入延遲高、Schema 固定 | 傳統集群、強一致性要求 |
| 內存數據網格 (Redis/Memcached) | 分布式 Hash 存儲 Session 對象 | 高性能、TTL 自動過期、集群原生 | 需額外基礎設施、序列化開銷 | 高併發、微服務、雲原生 (推薦) |
| Sticky Session + 本地存儲 | 負載均衡器基於 Cookie/IP 親和性路由 | 無序列化開銷、實現簡單 | 節點故障 Session 丟失、擴縮容困難 | 遷移期過渡、有狀態舊應用 |
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig {
// 自動配置 RedisOperationsSessionRepository
// 替換容器原生 Session 管理
// 支持 WebSocket、多標簽同步、REST API 無狀態認證
}
優勢:透明替換 `HttpSession` 實現、自動處理序列化 (Jackson JSON)、集成 Spring Security、提供 `FindByIndexNameSessionRepository` 支持查詢 (如踢出用戶所有會話)。
| 誤區 | 真相 | 正確做法 |
|---|---|---|
| Session 存大量數據 (購物車、報表) | 內存膨脹、序列化慢、複製開銷大 | 存儲 ID 關聯 Redis/DB,Session 僅存輕量引用 |
| 依賴 Session 實現業務邏輯 (如權限判斷) | 難測試、難擴展、耦合 Web 容器 | 權限數據讀取至 ThreadLocal/Request Scope,Service 層無感知 |
| 集群下直接用容器 Session 複製 (DeltaManager) | 全量廣播、網絡風暴、節點數>5 即崩潰 | 遷移至 Redis/JDBC Store 或 Spring Session |
| 以為關閉瀏覽器就銷毀 Session | 服務端無感知,仍佔用內存至超時 | 前端調用登出 API,或縮短超時時間 (如 10 分鐘) |
Session 是「有狀態」的租借,而非免費午餐。現代架構傾向於 無狀態服務 + 分布式會話存儲 (Redis) + 短效 JWT/Token,將 Session 降級為「兼容舊瀏覽器/特定場景」的輔助手段。掌握其原理、API、持久化選型與安全紅線,才能在遺遷與新建項目中做出正確決策。