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

Struts2 訪問 Web 核心對象:ActionContext 與接口注入兩種方式

     編輯:Java 相關知識

核心問題

Struts2 Action 默認非 Servlet API 依賴,如何獲取 request、session、application?提供兩種標準方案。

方式一:ActionContext 靜態訪問 (推薦簡單場景)

public class UserAction extends ActionSupport {
    private User user;
    
    public String register() {
        // 獲取 Map 形式的 request/session/application
        Map request = (Map) ActionContext.getContext().get("request");
        Map session = ActionContext.getContext().getSession();
        Map application = ActionContext.getContext().getApplication();
        
        // 存值
        request.put("username", user.getName());
        session.put("loginUser", user);
        
        return SUCCESS;
    }
    // getter/setter...
}

原理:ActionContext 是線程局部變量,每個請求獨立,內部持有 ServletRequestMap 等包裝類,操作最終委託給原生 Servlet API。

方式二:接口注入 (官方推薦,便於測試)

public class UserAction extends ActionSupport 
        implements RequestAware, SessionAware, ApplicationAware {

    private Map request;
    private Map session;
    private Map application;
    private User user;

    public String register() {
        request.put("username", user.getName());
        session.put("loginUser", user);
        return SUCCESS;
    }

    // 必須實現的 setter,Struts2 自動注入
    @Override public void setRequest(Map request) { this.request = request; }
    @Override public void setSession(Map session) { this.session = session; }
    @Override public void setApplication(Map application) { this.application = application; }
    
    // getter/setter...
}

接口定義在 org.apache.struts2.interceptor 包:

  • RequestAware → setRequest(Map)
  • SessionAware → setSession(Map)
  • ApplicationAware → setApplication(Map)
  • ParameterAware → setParameters(Map) (獲取所有請求參數)
  • ServletRequestAware → setServletRequest(HttpServletRequest) (直接拿原生對象)
  • ServletResponseAware → setServletResponse(HttpServletResponse)

JSP 頁面取值 (EL 表達式 / Struts 標簽)

<!-- EL 表達式 (推薦) -->
${requestScope.username}
${sessionScope.loginUser.name}

<!-- Struts2 標簽 -->
<s:property value="#request.username" />
<s:property value="#session.loginUser.name" />

兩種方式深度對比

維度ActionContext接口注入
代碼侵入性低(任意位置調用)需實現接口、聲明字段
單元測試難(依賴 ThreadLocal,需手動構建上下文)易(直接 new Action(), setRequest(mockMap))
類型安全Map 需轉型同樣,但字段可復用
生命周期隨時獲取當前請求上下文請求開始時注入,請求結束失效
推薦場景快速原型、工具方法、攔截器正式業務 Action、需單測項目

進階:直接注入原生 Servlet API

public class FileAction extends ActionSupport implements ServletRequestAware, ServletResponseAware {
    private HttpServletRequest request;
    private HttpServletResponse response;
    
    @Override public void setServletRequest(HttpServletRequest request) { this.request = request; }
    @Override public void setServletResponse(HttpServletResponse response) { this.response = response; }
    
    public String upload() {
        // 直接用 request.getInputStream()、response.getOutputStream()
        // 獲取真實路徑:request.getServletContext().getRealPath("/upload")
    }
}

⚠️ 注意:直接依賴 Servlet API 會降低可測試性,非必要不建議。

Struts2 核心對象生命周期圖解


請求到達
    ↓
FilterDispatcher / StrutsPrepareAndExecuteFilter
    ↓
創建 ActionContext (ThreadLocal)
    ↓
實例化 Action (或從 Spring 獲取)
    ↓
【接口注入】調用 setRequest/setSession/setApplication...
    ↓
調用 Action 方法 (execute / xxx)
    ↓
結果視圖渲染 (JSP/FTL/JSON)
    ↓
ActionContext 清理 (ThreadLocal remove)
    ↓
響應返回

最佳實踐總結

  1. 業務 Action 優先實現 XxxAware 接口,便於單測、符合 IoC 思想
  2. 工具類/攔截器/併發場景用 ActionContext.getContext()
  3. JSP 僅用 EL 表達式 (${requestScope.xxx}),不寫 Scriptlet
  4. 避免在 Action 構造函數/字段初始化中訪問 Web 對象,注入尚未發生
  5. Session 存儲對象實現 Serializable,支持集群 Session 複製

掌握這兩種訪問方式的本質區別與適用場景,是 Struts2 開發從「能跑通」到「工程化」的關鍵一步。

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