在 Spring 框架中,過濾器(Filter) 和 攔截器(Interceptor) 都是用于處理 HTTP 請求的中間件,但它們在作用范圍、實現方式和生命周期上有顯著區別。以下是詳細對比和實現方式:
核心區別
特性 | 過濾器 (Filter) | 攔截器 (Interceptor) |
---|---|---|
規范 | Servlet 規范 (J2EE 標準) | Spring 框架特有 |
作用范圍 | 所有 Web 資源(Servlet、JSP、靜態資源) | 僅 Spring MVC 管理的 Controller 請求 |
依賴 | 依賴 Servlet 容器(如 Tomcat) | 依賴 Spring 容器 |
攔截時機 | 在請求進入 Servlet 前 / 響應發送到客戶端前 | 在請求進入 Controller 前 / 后 / 視圖渲染后 |
獲取 Spring Bean | 不能直接獲取(需通過工具類) | 可直接獲取 Spring Bean |
異常處理 | 無法使用 Spring 的異常處理機制 | 可結合 @ControllerAdvice 統一異常處理 |
實現方式
1. 過濾器 (Filter) 實現
過濾器是 Servlet 規范的一部分,通過實現 javax.servlet.Filter
接口實現。
步驟:
- 創建 Filter 類
import javax.servlet.*;
import java.io.IOException;public class CustomFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) {// 初始化邏輯}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 1. 請求到達 Controller 前的邏輯System.out.println("Before Controller (Filter)");// 放行請求chain.doFilter(request, response);// 2. 響應返回客戶端前的邏輯System.out.println("After Controller (Filter)");}@Overridepublic void destroy() {// 銷毀邏輯}
}
- 注冊過濾器(Spring Boot 中)
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<CustomFilter> customFilter() {FilterRegistrationBean<CustomFilter> bean = new FilterRegistrationBean<>();bean.setFilter(new CustomFilter());bean.addUrlPatterns("/*"); // 攔截所有路徑bean.setOrder(1); // 執行順序return bean;}
}
2. 攔截器 (Interceptor) 實現
攔截器是 Spring MVC 的組件,通過實現 HandlerInterceptor
接口。
步驟:
- 創建 Interceptor 類
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;@Component
public class CustomInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 在 Controller 方法執行前調用System.out.println("Before Controller (Interceptor)");return true; // true=放行, false=中斷請求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {// 在 Controller 方法執行后、視圖渲染前調用System.out.println("After Controller (Interceptor)");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// 在整個請求完成后調用(視圖渲染完畢)System.out.println("After View Render (Interceptor)");}
}
- 注冊攔截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Autowiredprivate CustomInterceptor customInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(customInterceptor).addPathPatterns("/**") // 攔截所有路徑.excludePathPatterns("/login"); // 排除路徑}
}
執行順序示例
假設請求路徑被過濾器和攔截器同時攔截:
1. Filter: doFilter() [前邏輯]
2. Interceptor: preHandle()
3. Controller 方法執行
4. Interceptor: postHandle()
5. 視圖渲染
6. Interceptor: afterCompletion()
7. Filter: doFilter() [后邏輯]
如何選擇?
場景 | 推薦使用 |
---|---|
全局日志、字符編碼、安全過濾 | Filter |
權限驗證、參數預處理 | Interceptor |
需要 Spring 容器功能 | Interceptor |
非 Spring 項目 | Filter |
最佳實踐:優先使用 Interceptor(可集成 Spring 特性),若需處理靜態資源或深度請求/響應修改,則用 Filter。