摘要:本文深入分析 Spring Boot Web 项目中 Filter、Interceptor、ExceptionHandler 和 Controller AOP 四类组件的执行顺序,从源码层面揭示其背后的设计原理。
一、问题引入
当一个 HTTP 请求进入 Spring Boot 应用时,会经历如下一条处理链路:
请求 → Filter → Interceptor → AOP(Controller) → Controller → AOP(Controller)
↓
请求 ← Filter ← Interceptor ← AOP(Controller) ← ExceptionHandler ←
本文目标:明确这四类组件的先后顺序,并从 Spring MVC 架构和 Servlet 规范的角度解释其原理。
二、四类组件概述
2.1 Filter(过滤器)
Filter 是 Servlet 规范定义的组件,位于整个链路的最外层。
- 职责:请求预处理、响应后处理、通用逻辑(如登录校验、日志记录、跨域处理)
- 配置方式:
@WebFilter+@ServletComponentScan或FilterRegistrationBean - 作用范围:覆盖所有请求,包括静态资源
@WebFilter(urlPatterns = "/*")
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 执行(响应后)");
}
}
2.2 Interceptor(拦截器)
Interceptor 是 Spring MVC 提供的组件,在 DispatcherServlet 内部工作。
- 职责:请求级拦截,适合做业务无关的通用处理(如登录验证、权限校验)
- 配置方式:
implements WebMvcConfigurer+addInterceptors - 作用范围:仅拦截进入 Controller 的请求
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
System.out.println("Interceptor preHandle 执行");
return true; // false 时直接短路,不继续后续链路
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) {
System.out.println("Interceptor postHandle 执行");
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler,
Exception ex) {
System.out.println("Interceptor afterCompletion 执行");
}
}
2.3 ExceptionHandler(异常处理器)
ExceptionHandler 是 Spring MVC 统一异常处理的核心组件。
- 职责:捕获 Controller 抛出的异常,返回统一的错误响应
- 配置方式:
@ControllerAdvice+@ExceptionHandler - 作用范围:仅处理 Controller 层抛出的异常
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
System.out.println("ExceptionHandler 捕获异常:" + e.getMessage());
return ResponseEntity.status(500).body("系统错误");
}
}
2.4 AOP 切面(Controller 增强)
AOP(Aspect-Oriented Programming)是 Spring 提供的面向切面编程能力,可以对 Controller 方法进行增强。
- 职责:方法级横切关注点(如日志、事务、性能监控)
- 配置方式:
@Aspect+@Component+ 切入点表达式 - 作用范围:精确到方法级别
@Aspect
@Component
public class ControllerAop {
@Around("execution(* com.example.controller.*.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("AOP Before 执行");
Object result = joinPoint.proceed();
System.out.println("AOP After 执行");
return result;
}
}
三、执行顺序图解
完整执行顺序如下:
┌─────────────────────────────────────────────────┐
│ Filter Chain │
│ ┌──────────────────────────────────────────┐ │
│ │ DispatcherServlet │ │
│ │ ┌────────────────────────────────────┐ │ │
│ │ │ HandlerInterceptor │ │ │
│ │ │ ┌──────────────────────────────┐ │ │ │
│ │ │ │ Controller AOP │ │ │ │
│ │ │ │ ┌────────────────────────┐ │ │ │ │
│ │ │ │ │ Controller │ │ │ │ │
│ │ │ │ └────────────────────────┘ │ │ │ │
│ │ │ └──────────────────────────────┘ │ │ │
│ │ └────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
执行顺序(请求): Filter → Interceptor preHandle → AOP @Before → Controller
执行顺序(响应): Controller → AOP @After → Interceptor postHandle → Filter
异常处理顺序: Controller 异常 → AOP @AfterThrowing → ExceptionHandler
最终清理: Interceptor afterCompletion
四、源码层面的原理分析
4.1 Filter 最先执行 —— Servlet 规范决定
Filter 运行在 Servlet 容器层,独立于 Spring 容器之外。请求到达顺序:
Tomcat/Jetty (Servlet Container)
↓
Filter Chain(Filter 1 → Filter 2 → ... → Filter N)
↓
DispatcherServlet(Spring MVC 前端控制器)
原理:Servlet 规范要求所有请求必须经过 Filter 链,这发生在 Spring DispatcherServlet 之前。
4.2 Interceptor 在 DispatcherServlet 内部 —— Spring MVC 调度
DispatcherServlet 的核心方法 doDispatch() 源码简化如下:
// DispatcherServlet.doDispatch() 简化逻辑
protected void doDispatch(HttpServletRequest request,
HttpServletResponse response) {
// 1. 找到匹配的 Handler
HandlerExecutionChain handler = getHandler(request);
// 2. 应用 Interceptor 的 preHandle
if (!handler.applyPreHandle(request, response)) {
return; // preHandle 返回 false,直接短路
}
// 3. 执行业务逻辑(Controller)
HandlerAdapter adapter = getHandlerAdapter(handler.getHandler());
adapter.handle(request, response);
// 4. 应用 Interceptor 的 postHandle
handler.applyPostHandle(request, response);
// 5. 处理异常(包含在 doDispatch 中或由容器处理)
}
结论:Interceptor 是在 DispatcherServlet 调用 Controller 之前和之后执行的,因此它在 Filter 之后、Controller 之前。
4.3 Controller AOP 在 Interceptor 之后 —— AOP 代理机制
Spring AOP 的代理机制决定了它作用于方法级别:
实际执行链路:
Interceptor.preHandle()
↓
AOP Proxy(Spring 创建的代理对象)
↓
@Before 通知
↓
Controller 实际方法
↓
@After 通知
↓
@AfterReturning / @AfterThrowing
↓
Interceptor.postHandle()
原理:
- Spring AOP 基于代理模式:对 Controller 创建 JDK 动态代理或 CGLIB 代理
- 方法调用被代理对象拦截,执行切面逻辑后再调用真实目标方法
- Interceptor 拦截的是代理对象的调用,而非直接调用 Controller
- 因此 AOP 在 Interceptor 之后执行(进入时),但在 Interceptor 之前返回(返回链路相反)
4.4 ExceptionHandler 最后处理 —— 异常传播机制
异常抛出时的处理顺序:
Controller 抛出异常
↓
AOP @AfterThrowing(如果配置)
↓
DispatcherServlet 异常处理
↓
@ExceptionHandler 捕获
↓
Interceptors afterCompletion(始终执行)
↓
Filter(响应后处理)
关键点:
@ExceptionHandler只处理 Controller 层异常- Filter 和 Interceptor 的异常不会进入 ExceptionHandler
afterCompletion无论是否有异常都会执行(用于资源清理)
五、实测验证
创建以下测试代码验证顺序:
5.1 Filter
@Component
@Order(1)
public class TestFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain)
throws ServletException, IOException {
System.out.println("=== 1. Filter 执行 ===");
chain.doFilter(request, response);
System.out.println("=== 1. Filter 结束 ===");
}
}
5.2 Interceptor
@Component
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
System.out.println("=== 2. Interceptor preHandle ===");
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView mav) {
System.out.println("=== 4. Interceptor postHandle ===");
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) {
System.out.println("=== 6. Interceptor afterCompletion ===");
}
}
5.3 AOP 切面
@Aspect
@Component
public class TestAspect {
@Around("execution(* com.example.controller.*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("=== 3. AOP @Before ===");
Object result = pjp.proceed();
System.out.println("=== 5. AOP @After ===");
return result;
}
}
5.4 ExceptionHandler
@ControllerAdvice
public class TestExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handle(Exception e) {
System.out.println("=== ExceptionHandler 捕获异常 ===");
return ResponseEntity.status(500).body(e.getMessage());
}
}
5.5 Controller
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
System.out.println("=== 3.5. Controller 执行 ===");
return "OK";
}
}
5.6 执行结果
=== 1. Filter 执行 ===
=== 2. Interceptor preHandle ===
=== 3. AOP @Before ===
=== 3.5. Controller 执行 ===
=== 5. AOP @After ===
=== 4. Interceptor postHandle ===
=== 6. Interceptor afterCompletion ===
=== 1. Filter 结束 ===
六、异常场景的执行顺序
6.1 Controller 抛出异常
=== 1. Filter 执行 ===
=== 2. Interceptor preHandle ===
=== 3. AOP @Before ===
=== 3.5. Controller 执行(抛出异常)===
=== ExceptionHandler 捕获异常 ===
=== 6. Interceptor afterCompletion ===
=== 1. Filter 结束 ===
注意:postHandle 不会执行,因为异常在 postHandle 之前抛出。
6.2 Interceptor preHandle 返回 false
=== 1. Filter 执行 ===
=== 2. Interceptor preHandle 返回 false ===
=== 1. Filter 结束 ===
注意:后续所有组件都不执行。
七、各组件职责对比
| 组件 | 位置 | 职责场景 | 异常处理范围 |
|---|---|---|---|
| Filter | Servlet 容器层 | 跨系统关注点(认证、日志、跨域) | 所有异常(需 try-catch) |
| Interceptor | Spring MVC | 请求级拦截(权限、登录) | 需配合 afterCompletion |
| AOP | Spring 代理层 | 方法级横切(日志、事务) | 可通过 @AfterThrowing 处理 |
| ExceptionHandler | Spring MVC | 统一错误响应 | 仅 Controller 层异常 |
八、实际应用建议
8.1 Filter 适用场景
- 跨系统通用逻辑(OAuth 认证、请求日志)
- 编码处理、跨域设置
- 安全过滤(XSS 防护)
8.2 Interceptor 适用场景
- 业务无关的请求拦截(登录状态、Token 校验)
- 请求级数据绑定
- 性能日志
8.3 AOP 适用场景
- 方法级日志记录
- 事务管理
- 性能监控
- 缓存处理
8.4 ExceptionHandler 适用场景
- 统一的错误响应格式
- 业务异常转换
- 全局异常日志
8.5 执行顺序选择原则
Filter(最外层)→ 处理跨系统通用逻辑
↓
Interceptor(请求级)→ 处理业务无关的请求拦截
↓
AOP(方法级)→ 处理细粒度横切关注点
↓
Controller(业务逻辑)
原则:从外到内,职责粒度从粗到细。
九、总结
| 执行阶段 | 组件 | 原理 |
|---|---|---|
| 请求预处理 | Filter → Interceptor preHandle → AOP @Before | Servlet 规范 + DispatcherServlet 调度 + 代理模式 |
| 业务处理 | Controller | 实际业务逻辑 |
| 请求后处理 | AOP @After → Interceptor postHandle → Filter | 代理模式 + 逆向执行 |
| 异常处理 | ExceptionHandler | Spring MVC 统一异常处理机制 |
| 最终清理 | Interceptor afterCompletion | 无论成功或失败都执行 |
核心原理:
- Filter 最外层:由 Servlet 容器(Tomcat/Jetty)决定,独立于 Spring 生态
- Interceptor 在 DispatcherServlet 内部:由 Spring MVC 的
doDispatch()方法调度 - AOP 在 Controller 层:基于 Spring 代理模式,在方法级别生效
- ExceptionHandler 兜底:处理 Controller 层异常,提供统一响应
理解这个链路,对于设计请求处理流程、排查问题、优化性能都至关重要。
如果对你有帮助,欢迎点赞、收藏!有任何问题欢迎留言讨论。

1万+

被折叠的 条评论
为什么被折叠?



