Servlet Filter 原理分析與實戰
Servlet Filter 使用責任鏈模式實現Filter的調度執行,通過FilterChain管理Filter的執行,實現了Filter之間的邏輯解耦。本文簡化了Filter的擴展功能,可以清晰的看到責任鏈模式執行的骨架。
責任鏈模式
責任鏈目的:通過Chain封裝調用鏈路,實現Filter解耦
Chain 裏面維護了Filter集合,提供了Filter管理接口和調用下一個Filter的接口
class FilterChain {
// Filter 集合
List<Filter> filters = new ArrayList<>();
// 下一個 Filter 的下標
int idx;
/** 管理接口 add / update / remove */
public void addFilter(Filter filter) {
filters.add(filter);
}
/** 調用 下一個 Filter.doFilter */
public void doNextFilter() {
if (idx == filters.size()) {return;}
Filter filter = filters.get(idx++);
filter.doFilter(this);
}
}
Filter 只需要實現自己的邏輯,然後大喊 下一個 (chain.doNextFilter)
interface Filter {
void doFilter(FilterChain chain);
}
class LogFilter implements Filter {
@Override
public void doFilter(FilterChain chain) {
System.out.println(" log ------ start " );
// 調用 下一個
chain.doNextFilter();
System.out.println(" log ------ end " );
}
}
class AuthFilter implements Filter {
@Override
public void doFilter(FilterChain chain) {
System.out.println(" auth ------ start " );
// 調用 下一個
chain.doNextFilter();
System.out.println(" auth ------ end " );
}
}
責任鏈 核心 在於鏈的調度管理[Chain]
多個Filter 串行執行 形成調用鏈
Filter:單個Filter,實現自身的邏輯,調用下一個Filter
FilterChain:Filter鏈 維護一串Filters,提供下一個Filter的調用
實戰
@Component
@Order(2)
public class TransactionFilter implements Filter {
@Autowired
private HttpServletReqUtil reqUtil;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
final MyHttpServletRequestWrapper wrappedRequest = new MyHttpServletRequestWrapper(
(HttpServletRequest) request);
System.out.println("Inside Servlet Filter");
System.out.println("User IP address: " + reqUtil.getRemoteAddress(wrappedRequest));
System.out.println("Request Params: " + reqUtil.getRequestParams(wrappedRequest));
System.out.println("Request Payload: " + reqUtil.getPayLoad(wrappedRequest));
System.out.println("Exiting Servlet Filter");
chain.doFilter(wrappedRequest, response);
}
}
總結
- Filter通過責任鏈進行調用,由FilterChain統一管理調度,目的是解耦Filter
- Filter 適用場景:請求頭Header處理/ IP防刷 / 敏感詞過濾 / 資源訪問控制