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

借鑑 GenericServlet 設計模式實現可復用 HttpFilter 基類

     編輯:Java 綜合教學

動機

實現 Filter 接口時,必須實現 init()、doFilter()、destroy() 三個方法。但實際開發中,往往只關注核心過濾邏輯 doFilter(),而初始化與銷毀邏輯可能為空。若每個 Filter 都寫空方法,代碼冗餘且不美觀。參考 GenericServlet 的模板方法模式,我們可以封裝一個抽象基類 HttpFilter,簡化開發。

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() {
        // 子類可選重寫
    }
}

使用指南

  1. 繼承 HttpFilter:public class MyFilter extends HttpFilter
  2. 實現核心方法:僅需重寫 doFilter(HttpServletRequest, HttpServletResponse, FilterChain)
  3. 可選初始化:若需初始化參數,重寫無參 init(),內部調用 getFilterConfig() 獲取配置
  4. 可選銷毀:資源釋放時重寫 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 開發的最佳實踐之一。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved