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

Servlet Filter 過濾器完整指南:原理、配置與實戰範例

     編輯:Java 綜合教學

Servlet Filter 過濾器完整指南:原理、配置與實戰範例

什麼是過濾器?

過濾器是 Web 應用程式組件,可綁定至 Web 應用。不同於 Servlet,過濾器以「鏈」式串接在容器處理流程中:

  • 在 Servlet 處理請求之前攔截輸入請求
  • 在響應返回客戶端之前攔截輸出響應
  • 可檢查、修改請求與響應內容

過濾器適用場景

  • 為 Web 應用新增功能模組(無需修改底層程式碼即可增刪)
  • 為舊程式碼新增功能(如日誌、編碼、授權)

Filter 在容器結構中的位置

位於客戶端與目標資源(Servlet/JSP/HTML)之間,形成 Filter Chain。web.xml 中配置順序決定調用順序。也可配置初始化參數。

Filter 生命週期

init() → doFilter() → destroy()

由部署描述符中的 <filter> 元素驅動。Servlet 2.4 起支援請求分派器(<dispatcher>INCLUDE|FORWARD|REQUEST|ERROR</dispatcher>)。

Filter 核心介面方法

public interface Filter {
    void init(FilterConfig config) throws ServletException;
    void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
            throws IOException, ServletException;
    void destroy();
}

常見 Filter 類型

  • 授權 Filter:檢查用戶請求,過濾非法存取
  • 日誌 Filter:記錄特殊用戶請求詳情
  • 編碼 Filter:解決非標準編碼請求亂碼
  • XSLT Filter:轉換 XML 內容

實戰範例:雙重過濾器鏈

web.xml 配置

<!-- 日誌過濾器 -->
<filter>
    <filter-name>logfilter</filter-name>
    <filter-class>com.weijia.filterservlet.LogFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>logfilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 編碼過濾器 -->
<filter>
    <filter-name>setCharacterEncoding</filter-name>
    <filter-class>com.weijia.filterservlet.EncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>setCharacterEncoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

EncodingFilter - 編碼處理

public class EncodingFilter implements Filter {
    private String encoding;
    private Map<String, String> params = new HashMap<>();

    @Override public void init(FilterConfig config) {
        System.out.println("begin do the encoding filter!");
        encoding = config.getInitParameter("encoding");
        for (Enumeration<?> e = config.getInitParameterNames(); e.hasMoreElements();) {
            String name = (String) e.nextElement();
            params.put(name, config.getInitParameter(name));
        }
    }

    @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
            throws IOException, ServletException {
        System.out.println("before encoding " + encoding + " filter!");
        req.setCharacterEncoding(encoding);
        chain.doFilter(req, res);  // 關鍵:傳遞給下一個過濾器或目標資源
        System.out.println("after encoding " + encoding + " filter!");
    }

    @Override public void destroy() {
        System.out.println("end do the encoding filter!");
        params = null; encoding = null;
    }
}

LogFilter - 請求日誌記錄

public class LogFilter implements Filter {
    @Override public void init(FilterConfig config) {
        System.out.println("begin do the log filter!");
    }

    @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
            throws IOException, ServletException {
        System.out.println("before the log filter!");
        HttpServletRequest hreq = (HttpServletRequest) req;
        System.out.println("Log Filter攔截到請求路徑: " + hreq.getServletPath());
        try {
            chain.doFilter(req, res);
        } catch (Exception e) { e.printStackTrace(); }
        System.out.println("after the log filter!");
    }

    @Override public void destroy() {
        System.out.println("end do the log filter!");
    }
}

測試 Servlet

@WebServlet("/FilterServlet")
public class FilterServlet extends HttpServlet {
    @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        resp.setDateHeader("expires", -1);
    }
}

執行結果與調用關係

before the log filter!
Log Filter攔截到請求路徑:/FilterServlet
before encoding utf-8 filter!
after encoding utf-8 filter!
----------------------------------------
after the log filter!

Filter鏈調用關係圖

類似 C++ 建構/解構函數順序:web.xml 先配置的 Filter,init() 先執行,doFilter() 先進後出,destroy() 後執行。

重新部署時的生命週期

重新部署生命週期

容器先銷毀舊 Filter(逆序 destroy()),再初始化新 Filter(順序 init())。

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