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

Servlet 與 Filter 的核心差異與協作機制深度解析

     編輯:Java 相關知識

前言

在 Java Web 開發中,Servlet 與 Filter 是兩個核心組件,雖然它們都處理 HTTP 請求與回應,但職責與運作模式截然不同。本文將深入剖析兩者的生命週期、核心差異、鏈式調用機制,並附上實戰配置範例,幫助開發者釐清觀念、靈活運用。

核心差異一覽

特性ServletFilter
主要職責處理業務邏輯、產生動態回應預處理請求、後處理回應、通用邏輯複用
能否產生回應是,可直接輸出內容否,只能修改請求/回應物件
生命週期方法init、service、destroyinit、doFilter、destroy
調用方式容器根據 URL 映射直接調用鏈式調用,經由 FilterChain 傳遞
典型應用場景Controller、REST API、頁面渲染編碼過濾、權限驗證、日誌記錄、XSS 防護

Filter 生命週期詳解

1. 初始化階段 init(FilterConfig config)

Web 容器啟動時載入 Filter 實例,僅呼叫一次。可透過 FilterConfig 取得 <init-param> 設定的初始化參數(如字元編碼、白名單路徑等)。

2. 過濾階段 doFilter(request, response, chain)

每個請求到達時皆會觸發。核心邏輯:

  • 預處理:修改 ServletRequest/ServletResponse、記錄日誌、驗證權限等。
  • chain.doFilter(request, response):將控制權傳遞給鏈中下一個 Filter 或目標 Servlet。
  • 後處理:在 chain.doFilter 返回後,可修改回應標頭、壓縮輸出、計算耗時等。

3. 銷毀階段 destroy()

容器關閉或 Web 應用卸載前呼叫,用於釋放資源(關閉資料庫連線池、停止排程任務等)。

Filter 鏈式調用機制圖解

請求流向:Client → Filter1 → Filter2 → Filter3 → … → Target Servlet
回應流向:Target Servlet → … → Filter3 → Filter2 → Filter1 → Client

chain.doFilter() 如同一扇「雙向門」:請求通過時向下傳遞,回應返回時向上回溯。若某 Filter 未呼叫 chain.doFilter(),鏈條即中斷,後續 Filter 與 Servlet 皆不會被執行——這常用於權限攔截、快取直接回應等場景。

Web.xml 實戰配置範例

<!-- 編碼過濾器 -->
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>com.example.filter.EncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 登入驗證過濾器 -->
<filter>
    <filter-name>authFilter</filter-name>
    <filter-class>com.example.filter.AuthFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>authFilter</filter-name>
    <url-pattern>/secure/*</url-pattern>
</filter-mapping>

<!-- 目標 Servlet -->
<servlet>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>com.example.servlet.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>UserServlet</servlet-name>
    <url-pattern>/secure/user</url-pattern>
</servlet-mapping>

關鍵細節: <filter-mapping> 的順序決定鏈條順序;url-pattern 需精準匹配攔截路徑,避免過度攔截靜態資源。

Servlet 3.0+ 註解式配置

現代專案建議使用 @WebFilter 與 @WebServlet 替代 XML:

@WebFilter(urlPatterns = "/*", initParams = @WebInitParam(name="encoding", value="UTF-8"))
public class EncodingFilter implements Filter { ... }

@WebServlet("/secure/user")
public class UserServlet extends HttpServlet { ... }

常見誤區與最佳實踐

  • 誤區:在 Filter 中直接輸出回應內容 → 正確:Filter 應專注於橫切關注點,業務邏輯留給 Servlet/Controller。
  • 誤區:忘記呼叫 chain.doFilter() 導致請求卡死 → 正確:除非刻意攔截(如未登入導向登入頁),否則務必呼叫。
  • 最佳實踐:將共用邏輯(編碼、CORS、日誌、安全標頭)集中在 Filter,保持 Servlet 專注於業務流程。
  • 效能提示:Filter 鏈過長會增加延遲,合併同類邏輯、避免不必要的包裝類(HttpServletRequestWrapper)。

總結

Servlet 是「主角」,負責核心業務;Filter 是「幕後推手」,負責通用預處理與後處理。理解兩者的生命週期、鏈式協作與配置細節,能讓你設計出結構清晰、易維護且高效能的 Java Web 應用。

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