一、Filter
(过滤器)和 Interceptor
(拦截器)
在 SpringMVC 中,Filter
(过滤器)和 Interceptor
(拦截器)都是对请求和响应进行预处理和后处理的重要工具,但它们存在本质区别,属于不同层面的机制:

1-1、Filter(过滤器)
-
属于 Servlet 规范的一部分
-
和 Spring 无关,作用于整个 Web 应用(包括静态资源、Servlet、SpringMVC 控制器等)
-
是在 SpringMVC 前进行处理的。
1、使用场景:
-
编码处理(如统一设置 request 编码)
-
权限校验、登录验证(不依赖 Spring Bean)
-
请求日志记录
-
XSS 防护、跨域设置
2、编写方式:
java
@WebFilter(urlPatterns = "/*") // 或在 web.xml 中配置
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("Filter: 请求前...");
chain.doFilter(request, response); // 放行
System.out.println("Filter: 响应后...");
}
}
3、特点总结:
-
生命周期由 Servlet 容器管理
-
在 DispatcherServlet(SpringMVC 核心)之前执行
-
无法使用 Spring 的依赖注入(因为不是 Spring Bean)
1-2、Interceptor(拦截器)
-
是 SpringMVC 提供的机制
-
只会拦截进入 DispatcherServlet 的请求(也就是经过 SpringMVC 控制器的)
-
属于 Spring 容器管理,可以使用依赖注入
1、使用场景:
-
控制器权限校验(如登录检查)
-
日志记录、性能分析
-
国际化、视图数据填充
-
API 接口签名校验等
2、编写方式:
(1). 实现 HandlerInterceptor 接口:
java
public class MyInterceptor implements HandlerInterceptor {
// 请求前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("Interceptor: 控制器前");
return true; // false 则中断执行
}
// 控制器执行后,视图渲染前
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor: 控制器后");
}
// 完全结束后(包括视图渲染)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("Interceptor: 完成后");
}
}
(2). 注册拦截器(Java 配置方式):
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login", "/static/**");
}
}
3、特点总结:
-
生命周期由 Spring 管理,可注入 Bean
-
只拦截 Controller 请求,静态资源不会被拦截
-
更适合业务层逻辑(如认证授权、日志记录等)
1-3、两者对比总结:
对比项 | Filter | Interceptor |
---|---|---|
所属规范 | Servlet 规范 | Spring 框架 |
拦截范围 | 所有请求(静态资源、Servlet) | 只拦截 SpringMVC 控制器请求 |
执行时机 | DispatcherServlet 之前 | DispatcherServlet 之后 |
配置方式 | @WebFilter 或 web.xml |
实现 HandlerInterceptor 接口 |
注入 Spring Bean | 否 | 是 |
控制执行流程 | 不能直接终止控制器方法执行 | 可以通过 preHandle 控制是否继续 |
1-4、实际建议:
-
Filter: 用于与 Spring 无关的通用功能(如编码、日志、跨域等)
-
Interceptor: 用于控制器相关的逻辑(如登录校验、权限控制)
如果你只是处理 SpringMVC 控制器请求,推荐使用 Interceptor,它更灵活、易于与 Spring 的其他功能结合使用。
二、拦截器的执行流程图
浏览器请求在 SpringMVC 中的执行顺序:
java
1. 浏览器发送请求(HTTP 请求)
↓
2. Filter.doFilter()(过滤器处理)
↓
3. DispatcherServlet.doDispatch()
↓
3.1 调用 HandlerInterceptor.preHandle()(前置拦截器)
↓
4. Controller 方法执行(处理业务逻辑)
↓
5. HandlerInterceptor.postHandle()(后置拦截器:控制器执行后,视图渲染前)
↓
6. 视图解析与渲染(如返回 Thymeleaf、JSP、JSON 等)
↓
7. HandlerInterceptor.afterCompletion()(请求完成后,清理资源)
↓
8. Filter.doFilter() 后处理部分继续执行(回到过滤器的"响应后"部分)
↓
9. 响应返回给浏览器
阶段 | 处理组件 | 方法 | 说明 |
---|---|---|---|
1 | Filter | doFilter(request, response) |
最先执行的组件(如编码设置、日志) |
2 | DispatcherServlet | doDispatch() |
SpringMVC 核心分发器 |
3 | Interceptor | preHandle() |
在 Controller 前执行,可中断流程 |
4 | Controller | 处理请求的方法(比如 @GetMapping ) |
执行业务逻辑 |
5 | Interceptor | postHandle() |
Controller 执行后,视图渲染前 |
6 | 视图解析 | 渲染返回的页面或 JSON | 渲染 View、封装 Model |
7 | Interceptor | afterCompletion() |
整个请求执行完,做资源清理、异常处理等 |
8 | Filter | doFilter 后段 | Filter 的"响应后"逻辑 |
9 | 浏览器 | 展示响应结果 | 最终结果返回给用户 |
三、拦截器的配置
SpringMVC中的拦截器用于拦截控制器方法的执行
SpringMVC中的拦截器需要实现HandlerInterceptor接口;或者继承HandlerInterceptorAdapter类(已过时)
SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置:
3-1、步骤一:编写一个类,实现handerInterceptor接口
java
public class MyInterceptor implements HandlerInterceptor {
// 前置处理(Controller方法调用前)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("前置处理:preHandle");
return true; // 返回true才会继续调用后面的拦截器或Controller
}
// 后置处理(Controller方法调用后,但视图未渲染前)
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("后置处理:postHandle");
}
// 完成后处理(视图渲染后,一般用于资源清理)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("最终处理:afterCompletion");
}
}
重写里面的三个方法:
- preHandle
- postHandle
- afterCompletion(渲染视图之后)
3-2、在springMVC.xml中配置拦截器
1、配置方式一:bean
XML
<!-- 配置拦截器 -->
<mvc:interceptors>
<bean class="com.wsbazinga.controller.MyInterceptorController"></bean>
</mvc:interceptors>
页面返回值:

2、配置方式二:ref
XML
<!-- 配置拦截器 -->
<mvc:interceptors>
<!--<bean class="com.wsbazinga.controller.MyInterceptor"></bean>-->
<ref bean="myInterceptor"></ref>
</mvc:interceptors>
【注意】:
此时,拦截器类:MyInterceptor,要加上@Component注解,才能被IOC容器注入,并配置在ref中!
【注意】:方式一,方式二,所有的请求都会被拦截!
3、配置方式三:可以指定拦截
XML
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/> <!-- 拦截所有路径 -->
<mvc:exclude-mapping path="/login"/> <!-- 排除拦截的url -->
<bean class="com.example.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
【注意】:
拦截器和过滤器不同,拦截所有请求用的是:/**,而不是/*!
4、使用 Java 配置类(推荐,Spring Boot/Spring 5 常用)
java
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 WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns("/login", "/css/**", "/js/**"); // 放行登录、静态资源
}
}
四、多个拦截器的执行顺序
在 SpringMVC 中使用 多个拦截器 时,它们的执行顺序由你在配置时的注册顺序决定,就像"拦截器栈"。
4-1、多个拦截器的preHandle()都返回true
假设你注册了两个拦截器:
java
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new FirstInterceptor()).addPathPatterns("/**");
registry.addInterceptor(new SecondInterceptor()).addPathPatterns("/**");
}
那么执行顺序是:
方法名 | 执行顺序 |
---|---|
preHandle() |
先注册的先执行:First → Second(顺序) |
postHandle() |
先注册的后执行:Second → First(倒序) |
afterCompletion() |
先注册的后执行:Second → First(倒序) |
示例:假设两个拦截器打印日志
java
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(...) {
System.out.println("First - preHandle");
return true;
}
@Override
public void postHandle(...) {
System.out.println("First - postHandle");
}
@Override
public void afterCompletion(...) {
System.out.println("First - afterCompletion");
}
}
public class SecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(...) {
System.out.println("Second - preHandle");
return true;
}
@Override
public void postHandle(...) {
System.out.println("Second - postHandle");
}
@Override
public void afterCompletion(...) {
System.out.println("Second - afterCompletion");
}
}
输出结果将是:
java
First - preHandle
Second - preHandle
Second - postHandle
First - postHandle
Second - afterCompletion
First - afterCompletion
总结:
方法 | 顺序说明 |
---|---|
preHandle() |
注册顺序执行(1 → 2 → 3) |
postHandle() |
注册反向顺序(3 → 2 → 1) |
afterCompletion() |
注册反向顺序(3 → 2 → 1) |
如果中断请求 | 后续 preHandle() 不执行,已执行的 afterCompletion() 执行 |
4-2、多个拦截器中,有一个拦截器的 preHandle()
返回了 false
1、后续拦截器的 preHandle()
不会再执行
- 拦截链中断,SpringMVC 不会再往下调用后面的拦截器或 Controller 方法。
2、Controller 方法 不会被执行
- SpringMVC 直接终止请求流程,不会进入控制器。
3、已成功通过的拦截器(即 preHandle()
返回 true)的afterCompletion()
仍然会执行
- SpringMVC 会把之前已经通过的拦截器的
afterCompletion()
方法 按反顺序执行,用于清理资源。
示例:
假设我们注册了 3 个拦截器,顺序如下:
java
registry.addInterceptor(new Interceptor1());
registry.addInterceptor(new Interceptor2());
registry.addInterceptor(new Interceptor3());
拦截器2 的 preHandle()
返回 false
:
java
public class Interceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(...) {
System.out.println("Interceptor2 - preHandle");
return false; // 拦截住!
}
@Override
public void afterCompletion(...) {
System.out.println("Interceptor2 - afterCompletion");
}
}
打印结果将是:
java
Interceptor1 - preHandle
Interceptor2 - preHandle (返回 false,终止)
Interceptor1 - afterCompletion
注意:
-
Interceptor3
的任何方法都不会执行! -
postHandle()
都不会执行!因为 Controller 都没进去! -
afterCompletion()
只对 已成功通过的拦截器(即preHandle()
返回 true) 调用。