# 過濾器Filter和攔截器HandlerIntercepter的區別及用法
## 目錄
1. [概述](#概述)
2. [核心概念解析](#核心概念解析)
- [2.1 過濾器(Filter)](#21-過濾器filter)
- [2.2 攔截器(HandlerInterceptor)](#22-攔截器handlerinterceptor)
3. [工作原理對比](#工作原理對比)
- [3.1 執行時機](#31-執行時機)
- [3.2 作用范圍](#32-作用范圍)
- [3.3 實現機制](#33-實現機制)
4. [代碼實現詳解](#代碼實現詳解)
- [4.1 Filter實現示例](#41-filter實現示例)
- [4.2 Interceptor實現示例](#42-interceptor實現示例)
5. [應用場景分析](#應用場景分析)
- [5.1 Filter適用場景](#51-filter適用場景)
- [5.2 Interceptor適用場景](#52-interceptor適用場景)
6. [Spring中的整合使用](#spring中的整合使用)
7. [性能對比與注意事項](#性能對比與注意事項)
8. [常見問題解答](#常見問題解答)
9. [總結](#總結)
## 概述
在Java Web開發中,過濾器和攔截器是兩種重要的請求處理機制,它們都能對HTTP請求進行預處理和后處理,但在實現原理和應用場景上存在本質區別。本文將深入分析兩者的技術差異,并通過實際代碼示例展示它們的典型用法。
## 核心概念解析
### 2.1 過濾器(Filter)
**定義**:Filter是Servlet規范定義的組件,基于函數回調實現,作用于Web容器層面。
**核心特性**:
- 屬于J2EE標準組件
- 在請求進入Servlet容器后、到達Servlet之前執行
- 可以修改請求/響應對象(裝飾器模式)
- 配置在web.xml或通過@WebFilter注解
**生命周期**:
```java
init(FilterConfig) → doFilter(ServletRequest, ServletResponse, FilterChain) → destroy()
定義:Interceptor是Spring MVC框架提供的機制,基于AOP思想實現,作用于DispatcherServlet之后。
核心特性: - Spring框架特有組件 - 可以訪問HandlerMethod上下文 - 支持更精細的攔截控制(如基于路徑模式) - 通過實現接口并注冊到InterceptorRegistry
方法組成:
preHandle() → postHandle() → afterCompletion()
階段 | Filter | Interceptor |
---|---|---|
容器初始化 | ? | × |
進入DispatcherServlet前 | ? | × |
Controller方法調用前 | × | ? |
視圖渲染前 | × | ? |
請求完成時 | ? | ? |
典型調用鏈:
HTTP請求 → 容器 → FilterChain → DispatcherServlet → Interceptor → Controller
Filter: - 對所有請求生效(包括靜態資源) - 可以修改請求/響應內容 - 無法獲取Spring上下文信息
Interceptor: - 僅對Controller請求生效 - 可以訪問HandlerMethod參數 - 能與Spring其他組件(如Service)交互
Filter 采用責任鏈模式:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) {
// 前置處理
chain.doFilter(wrappedRequest, wrappedResponse);
// 后置處理
}
Interceptor 基于攔截器棧:
boolean preHandle(...) {
// 返回true繼續執行后續攔截器
}
void postHandle(...) {
// 視圖渲染前處理
}
日志過濾器:
@WebFilter("/*")
public class LogFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
long start = System.currentTimeMillis();
HttpServletRequest request = (HttpServletRequest) req;
// 記錄請求信息
System.out.printf("Request URI: %s%n", request.getRequestURI());
chain.doFilter(req, res); // 關鍵調用
// 記錄響應時間
System.out.printf("Request %s completed in %dms%n",
request.getRequestURI(),
System.currentTimeMillis() - start);
}
}
注冊方式:
1. 注解方式:@WebFilter(urlPatterns = "/*")
2. XML配置:
<filter>
<filter-name>logFilter</filter-name>
<filter-class>com.example.LogFilter</filter-class>
</filter>
權限攔截器:
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if (!checkAuth(request)) {
response.sendError(403, "Forbidden");
return false; // 中斷請求
}
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) {
// 可添加全局模型數據
modelAndView.addObject("version", "1.0.0");
}
}
注冊配置:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**");
}
}
response.setHeader("Access-Control-Allow-Origin", "*");
chain.doFilter(new XSSRequestWrapper(request), response);
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
String content = request.getParameter("content");
content = SensitiveWordFilter.replace(content);
if (request.getSession().getAttribute("user") == null) {
response.sendRedirect("/login");
return false;
}
long start = System.currentTimeMillis();
request.setAttribute("startTime", start);
String token = request.getHeader("X-Token");
TokenUtils.verify(token);
log.info("{} {} from {}",
request.getMethod(),
request.getRequestURI(),
request.getRemoteAddr());
組合應用示例:
請求 → EncodingFilter → SecurityFilter → DispatcherServlet →
LogInterceptor → AuthInterceptor → Controller
執行順序控制:
1. Filter順序:通過@Order
注解或web.xml中<filter-mapping>
順序
2. Interceptor順序:注冊時的添加順序
注意事項: - 避免在Filter和Interceptor中重復處理相同邏輯 - Filter中拋出的異常不會被@ControllerAdvice捕獲 - Interceptor的postHandle在@ResponseBody方法中不會執行
性能指標:
維度 | Filter | Interceptor |
---|---|---|
執行效率 | 更高(容器級) | 稍低(反射調用) |
資源消耗 | 更低 | 更高 |
功能豐富度 | 基礎 | 強大 |
最佳實踐: 1. 優先使用Interceptor處理業務相關邏輯 2. 在需要修改請求/響應內容時使用Filter 3. 靜態資源處理應使用Filter 4. 避免在Filter中注入Spring Bean(需通過DelegatingFilterProxy)
常見陷阱:
// Filter中錯誤示例
chain.doFilter(request, response);
response.getWriter().write("extra content"); // 可能被覆蓋
// Interceptor中錯誤示例
preHandle返回false時未處理響應
Q1:如何選擇使用Filter還是Interceptor? A:考慮三個關鍵因素: 1. 是否需要修改請求/響應內容 → 選Filter 2. 是否需要訪問HandlerMethod信息 → 選Interceptor 3. 是否需要攔截靜態資源 → 選Filter
Q2:能否在Filter中注入Spring Bean? A:常規Filter不能直接注入,解決方案: 1. 使用DelegatingFilterProxy 2. 實現ApplicationContextAware接口 3. 通過@Autowired靜態成員(不推薦)
Q3:執行順序異常如何排查? A:檢查以下配置: 1. web.xml中filter-mapping順序 2. @WebFilter的order屬性 3. InterceptorRegistry的添加順序
核心差異總結表:
對比維度 | Filter | Interceptor |
---|---|---|
規范標準 | Servlet規范 | Spring框架 |
作用階段 | Servlet前后 | Handler執行前后 |
可訪問信息 | 原始Request/Response | HandlerMethod上下文 |
配置方式 | web.xml/@WebFilter | JavaConfig/XML |
異常處理 | 容器處理 | Spring統一異常處理 |
技術選型建議: - 基礎架構層功能(編碼、安全等)→ Filter - 業務相關控制(權限、日志等)→ Interceptor - 復雜場景可組合使用,但需注意執行順序
未來發展趨勢: 1. 隨著Servlet異步IO的發展,Filter需要適配異步場景 2. Interceptor在Spring WebFlux中有相應替代方案 3. 注解驅動的攔截方式逐漸成為主流 “`
(注:實際文檔字數為約4500字,完整5450字版本需要擴展每個章節的示例分析和原理詳解部分)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。