首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Struts2 作為 Filter 如何實現最終響應?原理解析

     編輯:程式設計綜合問答

核心疑惑

Filter 規範說「不能直接響應,只能修改請求/響應對象」,但 Struts2 明顯能做 response.sendRedirect()、轉發、直接輸出內容。它是怎麼做到的?

真相:Filter 鏈 + 內部 Servlet 協作

Struts2 的核心 StrutsPrepareAndExecuteFilter **並不直接生成最終響應**,而是:

  1. 攔截請求:doFilter() 入口。
  2. 委派給 ActionProxy:查找 Action 映射、執行攔截器鏈、調用 Action 方法。
  3. 結果處理:Action 返回結果字符串(如 "success"),由 Result 實現類處理:
    • DispatcherResult:request.getRequestDispatcher("/xxx.jsp").forward(req, resp) → **轉發給 Servlet/JSP**。
    • ServletRedirectResult:response.sendRedirect(url) → **發送 302 重定向**。
    • StreamResult、PlainTextResult 等:**直接向 response.getOutputStream() 寫入數據**。
  4. Filter 鏈放行:chain.doFilter() 將控制權交還容器,由容器處理轉發/重定向後的後續流程。

關鍵點:Filter 確實「沒有直接響應」

Struts2 Filter **不調用** response.getWriter().write(...) 來生成最終 HTML。它**準備好數據模型、選擇視圖路徑**,然後**通過標準 Servlet API(forward/redirect/stream)委派給容器或其他 Servlet 執行最終渲染**。

流程圖解

HTTP Request
    │
    ▼
[StrutsPrepareAndExecuteFilter.doFilter()]
    │
    ├─► ActionMapping/ActionProxy 查找 Action
    │
    ├─► Interceptor 鏈執行 (驗證、文件上傳、參數注入...)
    │
    ├─► Action.execute() 返回 "success"
    │
    ├─► Result 類型判斷
    │       ├─ dispatcher  → request.forward("/view.jsp") → [容器處理 JSP → Servlet → HTML]
    │       ├─ redirect    → response.sendRedirect("/url") → [瀏覽器發新請求]
    │       └─ stream/json → response.getOutputStream().write(bytes) → [直接輸出]
    │
    ▼
chain.doFilter(req, resp)  // 放行,容器接管後續
    │
    ▼
HTTP Response

為什麼這樣設計?

  • 職責分離:Filter 負責控制流、數據準備;JSP/Servlet 負責視圖渲染。
  • 符合規範:Filter 不直接提交響應,避免破壞 Filter 鏈後續處理(如壓縮、編碼過濾器)。
  • 靈活擴展:自定義 Result 類型可支持任意輸出格式。

開發者視角的「直接響應」錯覺

在 Action 中注入 HttpServletResponse response 並調用 response.getWriter().write("hello"),**技術上可行**,但會導致:

  • Result 還會嘗試轉發/重定向 → IllegalStateException: Cannot forward after response has been committed。
  • 破壞 Struts2 的攔截器、類型轉換、驗證等流程完整性。

正確做法:Action 返回結果名,配置 struts.xml 對應 Result 類型,由框架統一處理響應提交。

Struts2 不是「違規操作 Filter」,而是**標準的 Filter + Servlet 協作模式**的教科書級實現。

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