軟體架構模式是系統級重用的核心資產。本文深度剖析「管道過濾器」架構模式的理論基礎、結構特性、優缺點,並以 Servlet 2.3 Filter、JBoss EJB 容器攔截器鏈、Axis Handler 鏈 三大 J2EE 經典實作為例,展示該模式在企業級中介軟體中的核心地位。
原水 → 沉澱池 → 過濾池 → 消毒池 → 加壓泵 → 管網 → 用戶端
每個處理單元獨立運作,透過管道連接,可獨立維護升級。
| 優點 | 缺點 |
|---|---|
| 替換/重組 Filter 極靈活 | 共享狀態昂貴或不靈活 (需額外上下文物件) |
| Filter 組件高度可重用 | 資料格式轉換額外開銷 (序列化/解析) |
| 快速原型 (管道組裝) | 錯誤處理複雜 (哪個 Filter 失敗?如何回滾?) |
| 並行處理潛力 (Pipe 並行) | 除錯困難 (資料流中間狀態不可見) |
public interface Filter {
void init(FilterConfig config) throws ServletException;
void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException;
void destroy();
}
// Filter 內部呼叫下一級
chain.doFilter(request, response); // 推模式:主動推送給下游
// 1. 編碼轉換 Filter
public class EncodingFilter implements Filter {
private String encoding = "UTF-8";
public void init(FilterConfig config) {
encoding = config.getInitParameter("encoding");
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
((HttpServletRequest)req).setCharacterEncoding(encoding);
chain.doFilter(req, res); // 傳遞給下一級 (安全 Filter)
}
}
// 2. 安全驗證 Filter
public class SignOnFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
// 安全檢查邏輯...
if (authorized) chain.doFilter(req, res); // 通過則繼續
else redirectToLogin(); // 失敗則短路,不呼叫 chain.doFilter
}
}
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.app.EncodingFilter</filter-class>
<init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param>
</filter>
<filter>
<filter-name>SignOnFilter</filter-name>
<filter-class>com.app.SignOnFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>SignOnFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
順序即正義:`web.xml` 宣告順序 = Filter 執行順序。
public class UCaseResponse extends HttpServletResponseWrapper {
public UCaseResponse(HttpServletResponse res) { super(res); }
public PrintWriter getWriter() {
return new UCaseWriter(super.getWriter()); // 包裝 Writer
}
}
public class UCaseWriter extends PrintWriter {
public void write(int c) { super.write(Character.toUpperCase((char)c)); }
// 重寫所有 write 方法...
}
// Filter 中使用
chain.doFilter(request, new UCaseResponse((HttpServletResponse)response));
LogInterceptor → SecurityInterceptor → TxInterceptorCMT → MetricsInterceptor
→ EntityLockInterceptor → EntityInstanceInterceptor → CachedConnectionInterceptor
→ EntitySynchronizationInterceptor → JDBCRelationInterceptor → Bean 實例
public class LogInterceptor extends AbstractInterceptor {
public Object invoke(Invocation invocation) throws Exception {
if (log.isTraceEnabled()) { /* 記錄呼叫詳情 */ }
return getNext().invoke(invocation); // 關鍵:傳遞給下一級攔截器
}
}
<container-interceptors>
<interceptor>org.jboss.ejb.plugins.LogInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.SecurityInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.TxInterceptorCMT</interceptor>
<interceptor metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntityLockInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntityInstanceInterceptor</interceptor>
<interceptor>org.jboss.resource.connectionmanager.CachedConnectionInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntitySynchronizationInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.cmp.jdbc.JDBCRelationInterceptor</interceptor>
</container-interceptors>
| 架構模式角色 | 對應 GoF 模式 | 應用場景 |
|---|---|---|
| Filter 鏈驅動 | Chain of Responsibility | 請求沿鏈傳遞,任一節點可處理或短路 |
| Filter 處理單元 | Command | 封裝請求為物件,支援排隊、日誌、撤銷 |
| Request/Response 包裝 | Decorator | 動態增強功能 (編碼轉換、壓縮、加密、大寫轉換) |
管道過濾器模式以「獨立 Filter + 統一資料流 + 可配置鏈」三大支柱,成為 J2EE 中介軟體基礎設施的核心架構範式。從 Servlet Filter 的請求預處理,到 JBoss 攔截器實現企業級服務品質 (交易、安全、鎖定),再到 Axis Handler 處理 SOAP 訊息流,無不體現此模式的強大生命力。現代架構中,Spring `