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

Struts 2 手動獲取請求參數、Session 與 Servlet API 完全指南

     編輯:Java 相關知識

當自動綁定無法滿足需求(如動態參數名、攔截器預處理、需直接操作 Servlet API)時,Struts 2 提供兩大核心上下文類:ActionContext(框架級、線程安全)與 ServletActionContext(Servlet 級、繼承前者)。

核心原理:ThreadLocal 隔離

ActionContext 內部靜態持有 ThreadLocal<ActionContext>,每個請求線程獨享上下文副本,保證線程安全。因此絕不可在構造函數或屬性初始化處調用 getContext() 或 getRequest(),必須在具體 Action 方法(execute()、login() 等)內調用,確保當前線程已綁定上下文。

方式一:ActionContext —— 框架解耦首選

ActionContext ctx = ActionContext.getContext();

// 1. 獲取請求參數 (Map<String, String[]>)
Map<String, String[]> params = ctx.getParameters();
String username = params.get("username")[0]; // 注意:值為數組

// 2. 獲取/設置 Session (Map<String, Object>)
Map<String, Object> session = ctx.getSession();
session.put("loginUser", user); // 相當於 session.setAttribute
User u = (User) session.get("loginUser");

// 3. 獲取 Request/Response (需 StrutsStatics 常量)
HttpServletRequest req = (HttpServletRequest) ctx.get(StrutsStatics.HTTP_REQUEST);
HttpServletResponse resp = (HttpServletResponse) ctx.get(StrutsStatics.HTTP_RESPONSE);
ServletContext sc = (ServletContext) ctx.get(StrutsStatics.SERVLET_CONTEXT);

優點:不依賴 Servlet API、單元測試友好(可 Mock Map)。
注意:Session 底層已被封裝為 Map,直接操作即可,無需取出 HttpSession。

方式二:ServletActionContext —— 直接訪問 Servlet 原生對象

// 必須在 Action 方法內調用!
HttpServletRequest req = ServletActionContext.getRequest();
HttpServletResponse resp = ServletActionContext.getResponse();
HttpSession session = req.getSession(); // 原生 HttpSession
ServletContext sc = ServletActionContext.getServletContext();
PageContext pageContext = ServletActionContext.getPageContext();

適用場景:需設定響應頭、Cookie、輸出流、文件上傳/下載等 Servlet 原生操作。

方式三:IoC 注入 (Aware 接口) —— 最符合 Struts 2 設計哲學

實作對應 Aware 接口,框架自動注入:

public class UserAction extends ActionSupport
        implements SessionAware, ServletRequestAware, ServletResponseAware {

    private Map<String, Object> session; // 注入 Session Map
    private HttpServletRequest request;
    private HttpServletResponse response;

    @Override public void setSession(Map<String, Object> session) { this.session = session; }
    @Override public void setServletRequest(HttpServletRequest request) { this.request = request; }
    @Override public void setServletResponse(HttpServletResponse response) { this.response = response; }

    public String login() {
        session.put("user", user); // 直接用 Map
        // 或用原生 request
        request.getSession().setAttribute("user", user);
        return SUCCESS;
    }
}

優點:依賴注入、無靜態調用、測試極易(直接傳 Map/Mock Request)。
原理:ServletConfigInterceptor 攔截器識別 Aware 接口並回調 Setter 注入。

選擇原則

  1. 能用 ActionContext 就不用 ServletActionContext,保持框架解耦。
  2. 優先用 Aware 接口注入,符合 IoC、最利測試。
  3. 構造函數/屬性初始化禁用靜態獲取,必須在 Action 方法內調用。

常見陷阱

  • ctx.getParameters() 返回 Map<String, String[]>,單值取 [0],多值(checkbox)遍歷數組。
  • ctx.getSession() 若 Session 未建立會自動創建,等同 request.getSession(true)。
  • 文件上傳必須用 ServletActionContext.getRequest() 獲取 MultipartRequest 或配合 FileUploadInterceptor 使用 File 屬性自動注入。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved