首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 2.5 存取 Session 屬性的四大策略深度解析

     編輯:Java 相關知識

前言:為什麼要脫離 Servlet API?

在 Web 應用程式開發中,Session 是維持伺服器端與客戶端之間狀態的關鍵機制,例如電商網站需在用戶登入後持續驗證身分權限。傳統做法直接在 Controller 中使用 HttpServletRequest 獲取 HttpSession,雖然直觀,卻造成程式碼強依賴 Servlet API,導致單元測試困難、程式碼耦合度高、難以復用。

Spring 2.5 引入註解驅動的 Controller 模型,提供了多種優雅的方式來存取 Session 屬性,本文將深入剖析四種核心策略,並從設計原則角度探討其優劣與適用場景。

策略一:直接注入 HttpSession / HttpServletRequest

最直觀的方式是在 Action 方法參數中聲明 HttpSession 或 HttpServletRequest,Spring 會自動綁定注入。

@RequestMapping
public void hello(HttpSession session) {
    User user = (User) session.getAttribute("currentUser");
    // 業務邏輯...
}

優點

  • 直接操作底層 API,簡單直接,對 Session 屬性存取控制精確到每個屬性。

缺點

  • 程式碼依賴 Servlet API,編譯、執行、測試皆需 Servlet 容器環境。
  • 暴露過多底層方法,開發者易濫用 API,違反「面向介面程式設計」原則。

策略二:攔截器在 Controller 層級注入

利用 Spring MVC 的 HandlerInterceptor,在 preHandle 階段將 User 物件注入實作特定介面(如 IUserAware)的 Controller 成員變數中。

public class UserInjectInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (handler instanceof IUserAware) {
            User user = (User) request.getSession().getAttribute("currentUser");
            ((IUserAware) handler).setUser(user);
        }
        return true;
    }
}

優點

  • Controller 脫離 Servlet API 依賴,更接近 POJO,利於測試與復用。
  • 透過介面標記注入目標,無繼承耦合,彈性較高。

缺點

  • Controller 預設為單例,成員變數存放請求級別資料易引發執行緒安全問題。
  • Setter 注入方式隱含風險:測試時若忘記注入,物件狀態不完整。
  • 本質上將 Action 級別的依賴上提至 Controller 級別,違反 Controller 無狀態慣例。

策略三:MethodArgumentResolver 在方法層級注入

Spring MVC 提供 WebArgumentResolver(後續版本為 HandlerMethodArgumentResolver)擴展點,針對 Action 參數類型進行自定義解析注入。

public class UserArgumentResolver implements WebArgumentResolver {
    public Object resolveArgument(MethodParameter param, NativeWebRequest webRequest) {
        if (param.getParameterType().equals(User.class)) {
            return webRequest.getAttribute("currentUser", RequestAttributes.SCOPE_SESSION);
        }
        return UNRESOLVED;
    }
}
@RequestMapping
public void hello(User user) {
    // 直接使用 user 物件
}

優點

  • 繼承策略二所有優點,且真正做到「按需分配」,依賴顯性化於方法簽名,API 更清晰。
  • 統一處理同類參數注入邏輯,維護性佳。

缺點

  • 注入粒度仍偏粗,針對所有 Action 生效,無法精確控制特定 Action 存取特定 Session 屬性。

策略四:@SessionAttributes + @ModelAttribute 註解驅動

利用 Spring MVC 內建的 @SessionAttributes 與 @ModelAttribute 協作,將 Session 中指定名稱的屬性自動綁定至 Action 參數。

優點

  • 完全脫離 Servlet API,Action 級別精確聲明所需 Session 屬性。
  • 依賴關係顯性化於參數與註解,程式碼可讀性極佳。

缺點

  • 若多個 Action 需同一屬性,需重複聲明註解,略顯冗餘。
  • 此用法非 @SessionAttributes 設計初衷(原為表單資料跨請求保持),可能引發語意爭議。

總結與架構思考

四種策略的演進路徑清晰可見:從「全域強耦合」→「Controller 層級注入」→「Action 層級統一注入」→「Action 層級精確聲明」。每種方案皆為特定上下文下的最優解:

  • 策略一:快速原型、舊系統維護、需直接操作 Session 完整生命週期時。
  • 策略二:跨切面統一注入少量共享物件(如權限上下文),且能接受 Prototype 作用域或執行緒局部變數替代方案時。
  • 策略三:大量 Action 共享同類型領域物件(如 User、Tenant),追求零樣板碼、統一解析邏輯時。
  • 策略四:強調介面契約、依賴顯性化、團隊偏好註解驅動開發、且可接受非標準用法風險時。

選型核心在於權衡「依賴反轉程度」、「注入粒度」、「程式碼冗餘度」與「語意純粹度」。建議團隊建立架構決策記錄(ADR),根據專案規模、團隊習慣、測試策略統一規範,避免專案中混用多種風格導致維護混亂。

後續文章將深入探討這些選擇背後的 OOP 設計原則(如單一職責、介面隔離、依賴反轉)在實戰中的體現,敬請期待。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved