Struts 2 通過 ServletActionContext 與 ActionContext 提供對 Servlet API 的無侵入式訪問,避免 Action 直接實現 ServletRequestAware 等接口造成耦合。本文匯總獲取 HttpServletRequest、HttpServletResponse、HttpSession、ServletContext、PageContext 的標準代碼,並說明原理與注意事項。
org.apache.struts2.ServletActionContext:靜態持有當前線程的 Servlet API 對象 (ThreadLocal 機制);com.opensymphony.xwork2.ActionContext:Struts 2 上下文,封裝 Session/Application 為 Map,與 Servlet API 解耦。import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import javax.servlet.http.*;
import javax.servlet.*;
// 1. HttpServletRequest
HttpServletRequest request = ServletActionContext.getRequest();
// 2. HttpServletResponse
HttpServletResponse response = ServletActionContext.getResponse();
// 3. HttpSession (原生)
HttpSession session = request.getSession(); // 或 request.getSession(false)
// 4. Session Map (Struts 2 封裝,單元測試友好)
Map<String, Object> sessionMap = ActionContext.getContext().getSession();
// 5. ServletContext (Application)
ServletContext application = ServletActionContext.getServletContext();
// 6. Application Map (Struts 2 封裝)
Map<String, Object> applicationMap = ActionContext.getContext().getApplication();
// 7. PageContext (極少用,僅 JSP 標籤協作需求)
PageContext pageContext = ServletActionContext.getPageContext();
| 方式 | 優點 | 缺點 | 推薦場景 |
|---|---|---|---|
ServletActionContext.getRequest() | 直接拿原生對象,功能全 | Action 與 Servlet API 耦合,單元測試需 Mock | 需訪問 Header、Cookie、InputStream、文件上傳等 Servlet 獨有功能 |
ActionContext.getContext().getSession() | 返回 Map,無 Servlet 依賴,易測試 | 無法直接操作 Session 屬性 (如 setMaxInactiveInterval) | 純業務邏輯存取 Session 屬性,單元測試場景 |
實現 ServletRequestAware 等接口 | IoC 注入,聲明式 | 侵入性強,Struts 1 風格,不推薦 | 遺遷移項目兼容 |
ActionContext.getContext() 依賴 ThreadLocal,**只能在請求處理線程中調用** (execute、interceptor),不能在構造函數、靜態初始化、異步線程中使用;getSession() 會自動創建,getSession(false) 才不創建;Map 方式同理;response.getWriter() 或 getOutputStream() 後再設 Header 會拋 IllegalStateException;request.getContentType().startsWith("multipart/") 並用 CommonsMultipartParser 或 Servlet 3.0 request.getPart() 解析,Struts 2 文件上傳攔截器已自動封裝為 File 屬性。Spring MVC 直接在方法參數聲明 HttpServletRequest request、HttpServletResponse response、HttpSession session、ServletContext application,由 HandlerMethodArgumentResolver 自動注入,**零耦合、極簡潔**,也是現代項目首選原因之一。
Struts 2 獲取原生 API:**首選 ServletActionContext 靜態方法**,需解耦測試時用 ActionContext Map 封裝。牢記 ThreadLocal 生命周期,避免異步/構造器中誤用。新項目建議直接上 Spring MVC,體驗聲明式注入優雅。