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

Struts2 StrutsPrepareAndExecuteFilter 核心字段解析與線程安全機制

     編輯:程式設計綜合問答

Filter 核心字段 (Struts 2.3.x)


public class StrutsPrepareAndExecuteFilter extends StrutsFilterBase {
    // 1. 準備階段操作封裝 (ActionMapping, Interceptor 等)
    protected PrepareOperations prepare;
    
    // 2. 執行階段操作封裝 (ActionInvocation, Result 執行)
    protected ExecuteOperations execute;
    
    // 3. 排除模式列表 (不經過 Struts 處理的靜態資源路徑)
    protected List excludedPatterns = null;
    
    // 4. 內部配置物件 (非公開字段)
    // protected ConfigurationManager configurationManager;
}

線程安全為何不成問題?

關鍵認知:Filter 實例是單例,但核心操作物件是請求範圍內創建的。

  1. prepare 和 execute 是無狀態的工具類實例,內部不持有請求相關資料。
  2. 每次請求進入 `doFilter()` 時,會創建新的 ActionContext、ActionInvocation、ValueStack 等請求級物件,這些物件儲存於 `ThreadLocal` (如 `ActionContext.getContext()`) 中,天然線程隔離。
  3. excludedPatterns 僅在初始化時讀取配置,運行期只讀,無並發寫入風險。

請求處理流程簡圖

HTTP Request
    ↓
StrutsPrepareAndExecuteFilter.doFilter()
    ↓
prepare.prepare(wrapper, chain)  // 建立 ActionContext, ActionMapping, 執行 PrepareInterceptor
    ↓
execute.execute(wrapper)         // 建立 ActionInvocation, 執行 Action + Interceptors + Result
    ↓
HTTP Response

常見誤區

「Filter 有字段 `prepare`/`execute` 會導致線程安全問題」—— 錯誤。這兩個字段指向的是無狀態的單例策略物件,真正的請求狀態在 `ThreadLocal` 中。

源碼關鍵片段 (doFilter)


public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    
    try {
        prepare.setEncodingAndLocale(request, response);
        prepare.createActionContext(request, response); // 關鍵:創建請求級 ActionContext (ThreadLocal)
        prepare.assignParams(request, response);        // 參數注入
        
        if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
            chain.doFilter(request, response);
            return;
        }
        
        ActionMapping mapping = prepare.findActionMapping(request, response);
        if (mapping == null) {
            chain.doFilter(request, response);
        } else {
            execute.executeAction(mapping, request, response); // 執行 Action 鏈
        }
    } finally {
        prepare.cleanupRequest(request); // 清理 ThreadLocal,防止記憶體洩漏
    }
}

總結

  • 三個主要字段:prepare、execute、excludedPatterns。
  • 線程安全靠 請求級物件 + ThreadLocal,而非 Filter 字段隔離。
  • 理解 PrepareOperations / ExecuteOperations 策略模式設計,有助於擴展自定義攔截邏輯。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved