前言:HTTP 無狀態與企業級有狀態需求的矛盾
Web 協議分無狀態與有狀態。HTTP 本質是無狀態協議,但企業級應用多數需要「記憶」跨請求的上下文(購物車、向導式流程、用戶權限等)。開發者發明了諸多技巧在 HTTP 上模擬有狀態:隱藏表單字段、URL 重寫、Cookie。
狀態管理可在Web 層或業務層實現,分別對應 HttpSession + Servlet 與 Stateful Session EJB 兩大技術棧。選型藝術在於權衡架構複雜度、性能、容錯與擴展性。
Web 層狀態管理:HttpSession 機制深度剖析
核心 API:HttpSession 接口
- 識別跨請求的單一客戶端
- 在伺服器端存儲與該客戶端關聯的數據
- 生命週期:創建 → 多次請求存活 → 超時/銷毀
- 核心能力:綁定/獲取屬性對象、獲取創建/訪問時間、失效控制
Servlet 容器如何追蹤無狀態 HTTP 下的會話?
每個 HttpSession 擁有唯一會話標識。每次請求必須攜帶該標識,容器攔截並關聯到正確的 Session 對象。三種傳遞方式:
- HTML 隱藏表單字段
- URL 重寫(查詢字符串附加)
- Cookie(最常用、最透明)
性能特徵:輕量級
- Session 內部本質是鍵值對雜湊表,存儲對象引用
- 輕量級線程模型不受影響
- 內存佔用極小(僅存儲 Session 對象與標識,或序列化持久化)
業務層狀態管理:Stateful Session Bean 全景
核心差異:有狀態 vs 無狀態
| 特性 | Stateless Session Bean | Stateful Session Bean |
| 生命週期 | 單次客戶請求 | 跨多個請求持續,維護對會話狀態 |
| 實例共享 | 池化複用,任一實例服務任一請求 | 專屬綁定,一客戶一實例 |
| 資源消耗 | 極低 | 高(佔用內存、需鈍化/激活) |
| 配置 | 部署描述符聲明 stateless | 部署描述符聲明 stateful |
EJB 容器提供的完整生命週期管理
- 無需特殊接口,容器自動管理創建、銷毀、鈍化、激活
- 鈍化:空閒超時將 Bean 狀態序列化至持久存儲(文件/數據庫)
- 激活:再次請求時從存儲恢復狀態到新實例
- 策略由廠商決定(LRU、NRU 等)
關鍵風險:伺服器崩潰導致狀態丟失
- 鈍化機制釋放資源,但無法防禦伺服器崩潰導致的活動狀態丟失
- 部分廠商提供會話恢復,但非標準,降低可移植性
- 標準解決方案:實現
javax.ejb.SessionSynchronization 接口,接收事務邊界回調(afterBegin、beforeCompletion、afterCompletion),在 Bean 內部正確處理事務狀態
性能代價:重量級機制
對比 Servlet 輕量級 HttpSession,Stateful Session Bean 需要:鈍化狀態 → 回收實例 → 激活狀態,每步涉及多次容器調用與回調,**性能開銷顯著**。
選型決策框架:七大關鍵問題
- 客戶端是否基於 Web(HTTP)?
- 對話狀態是否需滲透到 GUI 層?
- 伺服器預期負載如何?
- 有狀態組件是否需在伺服器崩潰後存活?
- 需要何種事務上下文?
- 有狀態數據的業務重要性?
- 是否存在多類型客戶端(Web + Rich Client)?
典型場景最佳實踐
1. 應用程序客戶端(Java/非 Java、防火牆內/外)
- 優先考慮 RMI + Stateless Session Bean(輕量)
- 需有狀態時:Stateless Bean + 事務層 或 薄 Servlet 層
- 極少數緊耦合跨請求業務流程:Stateful Session Bean
- 非 Java 客戶端可通過 IIOP 直接調用 EJB,繞過 Web 層
2. 電子商務隨需應變環境
- 核心:Stateless Session Bean(極致擴展性)
- 狀態管理:專用機制或 J2EE 事務
- 集成 CORBA 組件時:以 CORBA 方式調用 EJB
3. 「富」GUI 客戶端
- 跨防火牆:HTTP + Servlet(必要時後接 Session Bean)
- 同防火牆內:RMI 直連 Session Bean(Servlet 純屬開銷)
- 複雜事務管理:考慮 IIOP 調用 EJB 或 HTTP + Servlet + 業務委派模式
4. 標準 Web 應用
- Servlet 必不可少
- UI 綁定狀態 → HttpSession
- 跨請求業務流程三選一:
- Stateful Session Bean
- Stateless Bean + 服務端緩存 + HttpSession 存引用
- JavaBean 業務委派批量收集數據 + 最後提交 Stateless Bean
- 故障保護三選一:
- 支援狀態恢復的應用伺服器
SessionSynchronization 處理事務失敗
- Web 伺服器級 HttpSession 故障轉移 + 業務委派
5. 多客戶端類型混合場景
狀態管理策略與無狀態架構一致:Web 層統一入口,業務層共享組件。
結語
J2EE 無狀態架構有成熟藍圖,有狀態架構無標準配置,唯有權衡。核心決策點:狀態管理在 Web 層、業務層、還是雙層並行。理解 HttpSession 輕量與 Stateful Bean 重量的本質差異,結合業務語境、容錯要求、擴展預期,方能做出最適架構選擇。