實現 Filter 接口時,必須實現 init()、doFilter()、destroy() 三個方法。但實際開發中,往往只關注核心過濾邏輯 doFilter(),而初始化與銷毀邏輯可能為空。若每個 Filter 都寫空方法,代碼冗餘且不美觀。參考 GenericServlet 的模板方法模式,我們可以封裝一個抽象基類 HttpFilter,簡化開發。
package com.zhx.http.filter;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
public abstract class HttpFilter implements Filter, java.io.Serializable {
private static final long serialVersionUID = 1L;
private FilterConfig filterConfig;
/** 容器調用,僅一次,不建議子類重寫 */
@Override
public void init(FilterConfig config) throws ServletException {
this.filterConfig = config;
init(); // 調用無參模板方法
}
/** 供子類重寫的初始化模板方法 */
protected void init() throws ServletException {
// 默認空實現
}
/** 子類獲取 FilterConfig */
public FilterConfig getFilterConfig() {
return filterConfig;
}
/** 容器調用,轉型後委派給抽象 doFilter */
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (Exception e) {
throw new ServletException("non-HTTP request or response");
}
doFilter(request, response, chain);
}
/** 子類必須實現的核心過濾邏輯,直接使用 HTTP 專用類型 */
public abstract void doFilter(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws IOException, ServletException;
/** 容器調用銷毀,默認空實現 */
@Override
public void destroy() {
// 子類可選重寫
}
}
public class MyFilter extends HttpFilterdoFilter(HttpServletRequest, HttpServletResponse, FilterChain)init(),內部調用 getFilterConfig() 獲取配置destroy()init(config)、destroy()HttpServletRequest/Response,避免手動轉型FilterConfig 訪問,支持初始化參數讀取Serializable,支持容器序列化public class EncodingFilter extends HttpFilter {
@Override
public void doFilter(HttpServletRequest req, HttpServletResponse resp, FilterChain chain)
throws IOException, ServletException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
chain.doFilter(req, resp);
}
}
通過模板方法模式封裝 HttpFilter,將固定流程(轉型、配置保存)上移到基類,將變化點(過濾邏輯、初始化/銷毀細節)下放到子類,實現了代碼復用與關注點分離,是 Filter 開發的最佳實踐之一。