Spring MVC 拦截器与核心组件全解|过滤器、拦截器、AOP 深度对比
在 Java Web 开发中,Spring MVC 是后端最核心的 Web 框架,几乎所有 Spring Boot 项目的请求处理都基于其底层机制。很多开发者日常频繁使用拦截器、过滤器、全局异常处理等功能,但始终分不清 Filter、Interceptor、AOP 的层级差异和使用场景,也不了解完整的请求执行链路。
本文将从零详解 Spring MVC 拦截器核心原理、实战用法,区分三大切面机制的差异,并梳理 Spring MVC 全部核心组件的工作流程,帮你彻底吃透 Web 请求底层原理,适配面试和实战开发。
一、什么是 Spring MVC 拦截器(Interceptor)
拦截器是 Spring MVC 框架专属的请求切面扩展机制,基于 Spring AOP 思想实现,用于在 Controller 请求处理的前置、中置、后置阶段植入自定义逻辑。
它的核心优势是:不侵入业务代码,通过横切方式实现请求管控,且完美适配 Spring 容器,支持依赖注入、获取 Spring 上下文信息,是业务层请求拦截的首选方案。
1.1 核心顶层接口:HandlerInterceptor
自定义拦截器必须实现 HandlerInterceptor 接口,该接口定义了三个核心生命周期方法,覆盖请求全流程,执行时机各有不同:
✅ preHandle(前置拦截)
在 Controller 方法执行之前 触发。
-
返回
true:请求放行,继续执行后续流程 -
返回
false:直接中断请求,终止后续所有操作
核心场景:登录校验、JWT 令牌解析、接口权限校验、请求参数基础校验、接口限流。
✅ postHandle(中置处理)
在 Controller 方法执行完毕、视图渲染之前 触发。
可以获取并修改 ModelAndView 对象,调整视图数据、跳转路径,仅对模板视图项目有效。
注意:前后端分离项目(返回 JSON)该方法基本失效。
✅ afterCompletion(后置收尾)
在 整个请求完全结束(视图渲染完成/请求异常终止) 后触发,无论请求成功、报错、拦截终止,都会执行。
核心场景:资源释放、接口耗时统计、请求日志归档、异常信息记录、线程上下文清理。
1.2 实战代码:自定义登录拦截器
以最常用的未登录拦截跳转为例,实现基础的会话校验功能:
public class LoginInterceptor implements HandlerInterceptor {
/**
* 前置拦截:校验用户登录状态
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 排除静态资源、基础路径校验
String requestURI = request.getRequestURI();
// 从Session获取登录用户
Object user = request.getSession().getAttribute("loginUser");
if (user == null) {
// 未登录,重定向到登录页
response.sendRedirect("/login");
return false;
}
// 登录成功,放行请求
return true;
}
/**
* Controller执行后、视图渲染前执行
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) {
// 可自定义修改视图数据、跳转逻辑
}
/**
* 请求完全结束后收尾工作
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
// 清理线程资源、统计接口耗时
}
}
1.3 拦截器注册配置
拦截器定义后不会自动生效,需要通过实现 WebMvcConfigurer 接口完成注册、配置拦截路径和放行路径。
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
// 拦截所有请求
.addPathPatterns("/**")
// 放行登录、注册、静态资源、接口文档等无需拦截路径
.excludePathPatterns(
"/login",
"/register",
"/static/**",
"/favicon.ico",
"/doc.html"
);
}
}
1.4 多拦截器执行顺序(洋葱模型)
项目中可配置多个拦截器,Spring MVC 遵循洋葱模型执行,核心规则:
-
preHandle:按注册顺序正序执行
-
postHandle、afterCompletion:按注册顺序 逆序执行
举例:先注册拦截器 A,再注册拦截器 B
完整执行链路:
A.pre → B.pre → Controller 执行 → B.post → A.post → 视图渲染 → B.after → A.after
1.5 拦截器经典应用场景
-
用户登录、会话状态校验
-
JWT、Token 令牌解析与权限校验(RBAC)
-
接口访问日志记录、请求耗时统计
-
接口防重复提交、高频请求限流
-
请求头统一参数封装、透传(TraceId、租户ID)
二、过滤器(Filter)详解
很多新手容易混淆拦截器和过滤器,二者本质完全不同:Filter 是 Java EE 原生 Servlet 规范组件,不属于 Spring 框架,由 Tomcat、Jetty 等 Web 容器管理。
2.1 核心特性
-
作用层级:Web 容器最外层,优先于所有 Spring 组件执行
-
拦截范围:拦截所有 HTTP 请求,包括静态资源(html、js、css、图片)
-
Spring 支持:默认无法直接注入 Spring Bean,需特殊配置
-
依赖规范:原生 Servlet API,与 Spring 框架解耦
2.2 Filter 代码示例
@WebFilter(urlPatterns = "/api/*")
public class GlobalCorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 前置处理:设置跨域、编码格式
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setContentType("text/html;charset=UTF-8");
// 放行请求,进入下一个过滤器/拦截器
chain.doFilter(request, response);
// 后置处理:响应结果统一处理
}
}
2.3 Filter 经典应用场景
Filter 适合做全局通用、与业务无关的底层预处理:
-
全局请求编码统一设置
-
CORS 跨域统一处理
-
XSS、SQL 注入基础防护
-
全链路追踪 TraceId、日志ID 透传
三、Filter、Interceptor、AOP 三者深度对比
这三者是 Java Web 开发中最核心的三层横切机制,层级从外到内依次为:Filter → Interceptor → AOP。下面通过全方位对比,彻底区分三者差异。
| 对比维度 | Filter(过滤器) | Interceptor(拦截器) | AOP(切面) |
|---|---|---|---|
| 所属规范/框架 | Java EE Servlet 规范 | Spring MVC 框架 | Spring / AspectJ |
| 作用层级 | Web 容器层(最外层) | Spring MVC 框架层(中间层) | 业务方法层(最内层) |
| 拦截范围 | 所有请求(含静态资源) | 仅 Controller 接口请求 | 任意 Spring Bean 方法(Service/Controller) |
| Spring 依赖注入 | 不支持 | 原生支持 @Autowired | 原生支持 @Autowired |
| 核心上下文能力 | 仅能获取 Request/Response | 可获取 HandlerMethod、ModelAndView | 仅能获取方法参数、返回值、注解 |
| 全局异常捕获 | 无法被全局异常处理器捕获 | 可被 @RestControllerAdvice 捕获 | 可捕获,但无法修改 HTTP 状态码 |
| 核心用途 | 底层通用预处理(跨域、编码) | 业务请求管控(登录、权限) | 方法级增强(事务、缓存、日志) |
3.1 完整请求执行全链路(重中之重)
一次完整的 HTTP 请求,从接入到响应的完整执行顺序:
HTTP请求 → Filter过滤器 → DispatcherServlet → Interceptor.preHandle → Controller → AOP(@Before) → Service业务逻辑 → AOP(@After) → Interceptor.postHandle → 视图渲染 → Interceptor.afterCompletion → Filter后置处理 → HTTP响应
四、Spring MVC 全套核心组件详解
Spring MVC 并非只有拦截器,而是由一套完整的组件协同工作,完成请求分发、参数解析、业务执行、视图渲染、异常处理全流程。下面梳理所有核心组件的职责。
4.1 DispatcherServlet(前端控制器)
Spring MVC 核心入口、总调度中心。所有 HTTP 请求都会统一进入该组件,负责协调所有 MVC 组件,分发请求、调度流程,是整个框架的核心枢纽。
4.2 HandlerMapping(处理器映射器)
核心职责:根据请求 URL 匹配对应的 Controller 方法。
会扫描项目中所有@RequestMapping 注解,建立 URL 与处理器的映射关系,最终返回 HandlerExecutionChain(包含目标 Controller 方法 + 匹配的拦截器链)。
4.3 HandlerAdapter(处理器适配器)
负责适配不同类型的处理器,完成请求参数绑定、类型转换、数据校验,将 HTTP 请求参数封装为 Java 方法入参,最终调用执行目标 Controller 方法。
核心作用:统一适配不同格式的处理器,解耦请求分发与方法执行。
4.4 ModelAndView(模型视图封装)
封装一次请求的数据模型和视图信息:
-
Model:存储业务查询数据,用于视图渲染展示
-
View:存储逻辑视图名称,用于匹配物理视图文件
⚠️ 前后端分离项目中,通过 @ResponseBody 直接返回 JSON 数据,不会使用视图渲染,该组件基本不生效。
4.5 ViewResolver(视图解析器)
将 Controller 返回的逻辑视图名解析为真实的物理视图文件,完成页面渲染。
常用实现类:
-
InternalResourceViewResolver:传统 JSP 视图解析器 -
ThymeleafViewResolver:主流 Thymeleaf 模板视图解析器
4.6 HandlerExceptionResolver(全局异常处理器)
统一拦截处理 Controller、Service 执行过程中的所有异常,避免原生异常堆栈直接返回前端,实现统一异常响应、友好提示。
日常开发常用注解:
-
@ExceptionHandler:单个控制器内方法级异常处理 -
@RestControllerAdvice:全局统一异常处理(前后端分离必备) -
ResponseStatusExceptionResolver:自定义异常映射 HTTP 状态码
五、核心总结与开发规范
通过三层横切机制 + MVC 核心组件,Spring MVC 实现了请求分层处理、职责单一解耦的设计思想,实际开发中严格遵循以下分工原则:
-
Filter(最外层):只做容器级通用操作,跨域、编码、安全过滤、链路ID透传,不处理业务逻辑
-
Interceptor(中间层):专注接口业务管控,登录校验、权限拦截、请求日志、限流防重
-
AOP(最内层):专注方法级增强,事务控制、缓存操作、接口性能监控、日志记录
三者各司其职、配合使用,既能保证代码解耦,又能实现复杂的 Web 请求管控逻辑,也是面试中 Spring MVC 模块的核心考点。
970

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



