Spring Boot過濾器的那些事:從配置到應用場景
1. 什么是過濾器
過濾器是 Web 三大組件之一,也是項目中常用的工具。本文主要介紹過濾器的概念及在 Spring Boot 中的常用使用方法。
過濾器由 Servlet 提供,基于函數回調實現鏈式對網絡請求和響應的攔截與修改。由于基于 Servlet,幾乎可以攔截 Web 服務器管理的所有資源(JSP、圖片文件、HTML 文件、CSS 文件等)。
定義過濾器需要實現javax.servlet.Filter
接口。過濾器不是 Servlet,無法直接生成對客戶端的響應,只能攔截已有請求并預處理不需要或不一致的信息資源。
2. 過濾器流程原理
在 Web 應用中,可以開發編寫多個過濾器,這些過濾器組合稱為過濾器鏈。用戶發起請求后,請求信息會按過濾器鏈中過濾器的順序依次進入每個過濾器。經過每層過濾器時,需通過過濾器的校驗邏輯并放行才能進入下一層過濾器,直至服務器獲取資源。
服務器成功獲取資源并響應過濾器后,會按反向順序經過層層過濾器,最終響應用戶。
3. 過濾器分類
Servlet 2.5:
- REQUEST: 用戶直接訪問頁面時,WEB 容器會調用過濾器鏈。
- FORWARD: 通過 RequestDispatcher 的 forward 訪問目標資源時調用此過濾器。
- INCLUDE: 通過 RequestDispatcher 的 include 方法調用目標資源時調用。
- ERROR: 通過聲明式異常處理機制調用目標資源時調用過濾器鏈。
Servlet 3.0:
- ASYNC: 支持異步處理。
4. 過濾器中需要實現的方法
public void doFilter(ServletRequest, ServletResponse, FilterChain)
: 實現實際過濾操作。當客戶端請求方法與過濾器設置的 URL 匹配時,Servlet 容器會先調用過濾器的 doFilter 方法。FilterChain 用于訪問后續過濾器。public void init(FilterConfig filterConfig)
: Web 應用啟動時,Web 服務器創建過濾器實例對象并調用其 init 方法完成對象初始化(過濾器對象僅創建一次,init 方法僅執行一次)。開發者可通過 init 方法參數執行讀取配置文件等初始化操作。public void destroy()
: Servlet 容器銷毀過濾器實例前調用此方法。用于釋放過濾器占用的資源。
5. 創建過濾器的兩種方式
方法一:注解方式
創建步驟:
- 實現
Filter
接口,添加@WebFilter
和@Order
注解配置過濾器:
@Order(1)
@WebFilter(filterName = "myFilter", urlPatterns = {"*"})
public class MyCustomFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {}
@Override
public void destroy() {}
}
- 在啟動類添加
@ServletComponentScan
注解:
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
方法二:將過濾器注冊為 Bean
創建步驟:
- 創建實現 Filter 接口的過濾器類:
public class MyCustomFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain){}
@Override
public void destroy() {}
}
- 創建過濾器配置類,注冊過濾器:
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean customFilter(){
FilterRegistrationBean<MyCustomFilter1> filterBean = new FilterRegistrationBean<>();
filterBean.setFilter(new MyCustomFilter1());
filterBean.setName("FilterController");
filterBean.addUrlPatterns("/*");
return filterBean;
}
}
6. 注解方式的參數說明與使用示例
(1)參數說明
@WebFilter
可配置多個參數,部分參數說明如下:
參數名稱 | 參數類型 | 參數描述 |
filterName | String | 過濾器的名稱 |
displayName | String | 要顯示的過濾器名稱 |
asyncSupported | boolean | 設置過濾器是否支持異步模式 |
initParams | WebInitParam[] | 你可以在初始化時配置一些參數 |
servletNames | String[] | 設置要過濾的 Servlets |
urlPatterns | String[] | 指定要攔截的路徑 |
value | String[] | urlPatterns 屬性與 urlPatterns 屬性的作用相同,兩者都指定要攔截的路徑 |
dispatcherTypes | DispatcherType[] | 設置過濾器過濾的請求類型,支持以下屬性:ASYNC, ERROR, FORWARD, INCLUDE, REQUEST(默認情況下,它過濾所有類型的請求) |
(2)使用示例
- 創建 Controller 類
@RestController
publicclass TestController {
@GetMapping("/a/hello")
public String hello1(){
return"hello world! a";
}
@GetMapping("/b/hello")
public String hello2(){
return"hello world! b";
}
@GetMapping("/c/hello")
public String hello3(){
return"hello world! c";
}
}
- 創建過濾器類
@Order(1)
@WebFilter(filterName = "myFilter", urlPatterns = {"/a/*", "/b/*"}, description = "自定義過濾器")
publicclass MyCustomFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) {
System.out.println("過濾器初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("請求處理前...");
chain.doFilter(request, response); // 放行請求
System.out.println("請求處理后...");
}
@Override
public void destroy() {
System.err.println("過濾器銷毀");
}
}
- 創建啟動類
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
7. 過濾器注冊 Bean 方式的參數說明與使用示例
(1)方法參數說明
方法名稱 | 方法描述 |
setName() | 設置過濾器的名稱。 |
setFilter() | 設置要注冊的過濾器。 |
setOrder() | 設置過濾器的順序位置。 |
setAsyncSupported() | 設置過濾器是否支持異步模式。 |
addUrlPatterns() | 添加攔截的路徑。 |
setUrlPatterns() | 設置攔截的路徑。 |
addServletNames() | 添加過濾器的 servlet 名稱。 |
setServletNames() | 設置注冊過濾器的 servlet 名稱。 |
setInitParameters() | 設置初始化參數。 |
addInitParameter() | 添加初始化參數。 |
setMatchAfter() | 設置是否在 Servlet 上下文中聲明的任何過濾器映射之后匹配過濾器映射。 |
setDispatcherTypes() | 設置過濾器過濾的請求類型。支持的屬性如下:ASYNC, ERROR, FORWARD, INCLUDE, REQUEST(默認情況下,它過濾所有類型的請求)。 |
(2)使用示例
- 創建 Controller 類
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
publicclass TestController {
@GetMapping("/a/hello")
public String hello1(){
return"hello world! a";
}
@GetMapping("/b/hello")
public String hello2(){
return"hello world! b";
}
@GetMapping("/c/hello")
public String hello3(){
return"hello world! c";
}
}
- 創建過濾器類
public class MyCustomFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) {
System.out.println("過濾器初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("請求處理前...");
chain.doFilter(request, response); // 放行請求
System.out.println("請求處理后...");
}
@Override
public void destroy() {
System.err.println("過濾器銷毀");
}
}
- 創建過濾器配置類
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean customFilter(){
FilterRegistrationBean<MyCustomFilter1> filterBean = new FilterRegistrationBean<>();
filterBean.setFilter(new MyCustomFilter1());
filterBean.setName("FilterController");
filterBean.addUrlPatterns("/c/*","/b/*");
return filterBean;
}
}
- 創建啟動類
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
8. 過濾器使用場景
(1)日志記錄
過濾器可記錄請求和響應的關鍵信息,便于排查問題和分析系統運行狀態。例如記錄請求 URL、參數、響應狀態碼等。
(2)數據統計
用于采集各類數據指標,如統計請求次數、響應時間分布等,為系統優化提供依據。
(3)數據格式轉換
不同系統交互時,過濾器可轉換數據格式,例如將 JSON 轉為 XML。
(4)為數據設置默認值
檢查輸入數據,為缺失字段設置默認值,保證數據完整性。
(5)權限認證、黑白名單
實現用戶權限認證和訪問控制,限制特定 IP 或用戶的訪問。
(6)數據加解密、簽名驗證
對敏感數據加解密以保證安全,同時進行簽名驗證確保數據完整性。