責任鏈模式將請求的發送者與接收者解耦:多個處理者對象組成一條鏈,請求沿鏈傳遞,直到某個處理者處理它或到達鏈尾。發送者無需知道誰最終處理請求。
| 角色 | 說明 |
|---|---|
| Handler (抽象處理者) | 定義處理請求接口 handleRequest(),持有 successor 引用 |
| ConcreteHandler (具體處理者) | 實現處理邏輯:處理或轉發 successor.handleRequest() |
// 抽象處理者
public abstract class Handler {
protected Handler successor;
public void setSuccessor(Handler s) { this.successor = s; }
public abstract String handleFeeRequest(String user, double fee);
}
// 具體處理者
public class ProjectManager extends Handler {
@Override public String handleFeeRequest(String user, double fee) {
if (fee < 500) {
return "張三".equals(user) ?
"成功:項目經理批准【" + user + "】" + fee + "元" :
"失敗:項目經理駁回【" + user + "】" + fee + "元";
}
return successor != null ? successor.handleFeeRequest(user, fee) : "無人審批";
}
}
public class DeptManager extends Handler {
@Override public String handleFeeRequest(String user, double fee) {
if (fee < 1000) {
return "張三".equals(user) ?
"成功:部門經理批准【" + user + "】" + fee + "元" :
"失敗:部門經理駁回【" + user + "】" + fee + "元";
}
return successor != null ? successor.handleFeeRequest(user, fee) : "無人審批";
}
}
public class GeneralManager extends Handler {
@Override public String handleFeeRequest(String user, double fee) {
if (fee >= 1000) {
return "張三".equals(user) ?
"成功:總經理批准【" + user + "】" + fee + "元" :
"失敗:總經理駁回【" + user + "】" + fee + "元";
}
return successor != null ? successor.handleFeeRequest(user, fee) : "無人審批";
}
}
// 客戶端組裝鏈
public class Client {
public static void main(String[] args) {
Handler pm = new ProjectManager();
Handler dm = new DeptManager();
Handler gm = new GeneralManager();
pm.setSuccessor(dm);
dm.setSuccessor(gm);
System.out.println(pm.handleFeeRequest("張三", 300)); // 項目經理批准
System.out.println(pm.handleFeeRequest("李四", 300)); // 項目經理駁回
System.out.println(pm.handleFeeRequest("張三", 700)); // 部門經理批准
System.out.println(pm.handleFeeRequest("張三", 1500)); // 總經理批准
}
}
ApplicationFilterChain:責任鏈核心,實現 FilterChain 接口,持有 ApplicationFilterConfig[] filters 數組與位置指針 pos。ApplicationFilterConfig:Filter 包裝器,持有 Filter 實例與配置元數據。ApplicationFilterFactory:構建 Filter 鏈,從 StandardContext 讀取 web.xml 配置,實例化 Filter 並加入鏈。StandardWrapperValve.invoke() 調用 ApplicationFilterFactory.createFilterChain()。ApplicationFilterChain,遍歷 FilterMap,匹配 URL/Servlet 名稱。StandardContext 獲取 ApplicationFilterConfig,調用 filterChain.addFilter(config) 加入數組。filterChain,閥門調用 filterChain.doFilter(req, res) 啟動鏈。
// ApplicationFilterChain.internalDoFilter()
if (pos < n) {
ApplicationFilterConfig config = filters[pos++];
Filter filter = config.getFilter();
// 安全管理器檢查...
filter.doFilter(request, response, this); // 關鍵:傳遞 this (FilterChain) 讓 Filter 可繼續調用
}
用戶 Filter 實現:
public class MyFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
// 前置邏輯
chain.doFilter(req, res); // 必須調用,否則鏈中斷
// 後置邏輯
}
}
在 StandardWrapperValve.invoke() 斷點可見調用棧:invoke → createFilterChain → addFilter (多次) → doFilter → internalDoFilter → filter.doFilter → chain.doFilter → ...
| 優點 | 缺點 |
|---|---|
| 降低耦合:發送者無需知曉具體處理者 | 性能開銷:請求需遍歷鏈,深鏈延遲明顯 |
| 靈活性:可動態增刪/重排處理者 | 調試困難:邏輯分散在多個類,調用鏈長 |
| 單一職責:每個處理者只關注特定業務 | 循環引用風險:誤配置可能導致死循環 |
handleRequest。CompletableFuture 或使用 Reactor 模式。