在 Java Web 開發中,Filter(過濾器/攔截器) 是一個實現 javax.servlet.Filter 介面的類別,主要用於攔截對 Servlet 的請求與響應。它能在 Servlet 處理請求前後執行特定邏輯,常見應用包括:字符編碼統一、權限驗證、日誌記錄、敏感詞過濾、壓縮響應等。
Filter 介面定義了三個關鍵方法,掌握它們的調用時機至關重要:
FilterConfig 獲取初始化參數(如 <init-param>),必須在這裡完成,構造函數無法獲取該對象。chain 代表過濾器鏈,必須調用 chain.doFilter(request, response) 才能將請求傳遞給下一個 Filter 或目標 Servlet,否則請求會被攔截終止。package com.net;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Index extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("Index");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
package com.net;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyFilter implements Filter {
public void init(FilterConfig fConfig) throws ServletException {
System.out.println("MyFilter.init()");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
PrintWriter out = response.getWriter();
out.println("Hello MyFilter"); // 在目標 Servlet 之前輸出
chain.doFilter(request, response); // 傳遞給下一個環節
}
public void destroy() {
System.out.println("MyFilter.destroy()");
}
}
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.net.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/Index</url-pattern> <!-- 攔截 /Index 路徑 -->
</filter-mapping>
<servlet>
<servlet-name>Index</servlet-name>
<servlet-class>com.net.Index</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Index</servlet-name>
<url-pattern>/Index</url-pattern>
</servlet-mapping>
訪問 /Index,控制台輸出 MyFilter.init(),頁面顯示:
Hello MyFilter
Index

當配置多個 Filter 攔截同一路徑時,會形成責任鏈模式。調用順序取決於 web.xml 中 <filter-mapping> 的聲明順序。
public class MyFilter2 implements Filter {
public void init(FilterConfig fConfig) throws ServletException { }
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
PrintWriter out = response.getWriter();
out.println("Hello MyFilter2 Start");
chain.doFilter(request, response); // 關鍵:執行完後續邏輯再返回
out.println("Hello MyFilter2 End"); // 響應階段輸出
}
public void destroy() { }
}
<filter> <filter-name>MyFilter</filter-name> <filter-class>com.net.MyFilter</filter-class> </filter>
<filter-mapping> <filter-name>MyFilter</filter-name> <url-pattern>/Index</url-pattern> </filter-mapping>
<filter> <filter-name>MyFilter2</filter-name> <filter-class>com.net.MyFilter2</filter-class> </filter>
<filter-mapping> <filter-name>MyFilter2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 攔截所有路徑 -->
<servlet> ... </servlet> <servlet-mapping> ... </servlet-mapping>

請求階段: Request → MyFilter → MyFilter2 → Index(Servlet)
響應階段: Response ← MyFilter ← MyFilter2 ← Index(Servlet)
注意:MyFilter2 的 chain.doFilter() 之後的代碼會在響應返回時執行,這雙向特性是實現「請求預處理 + 響應後處理」的關鍵。

init();關閉時調用 destroy()。全生命週期只有一個實例,init() 僅執行一次。web.xml 中的註冊信息,提供獲取初始化參數、Filter 名稱、ServletContext 等方法。
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.net.MyFilter</filter-class>
<init-param>
<param-name>like</param-name>
<param-value>java</param-value>
</init-param>
</filter>
public void init(FilterConfig fConfig) throws ServletException {
System.out.println("MyFilter.init()");
String filterName = fConfig.getFilterName(); // 獲取 filter-name
String initParam = fConfig.getInitParameter("like"); // 獲取 init-param 值
System.out.println(filterName); // 輸出: MyFilter
System.out.println(initParam); // 輸出: java
}
web.xml 中 <filter-mapping> 順序決定執行順序,設計時務必規劃好。destroy() 中關閉數據源、線程池等長連接資源。@WebFilter 註解或 FilterRegistrationBean 程式化配置,減少 XML 依賴。Filter 是 Java Web 基礎設施的基石,深入理解其生命週期與鏈式機制,對構建健壯、可維護的 Web 應用至關重要。