Spring Boot一次接口请求涉及的完整执行链路
Spring Boot一次接口请求涉及的完整执行链路
🔁 Spring 项目请求执行链路(简化视图)
客户端请求(浏览器、Postman)↓
Tomcat(Servlet 容器)↓
【Listener 监听器】↓
【Filter 过滤器】(如安全认证)↓
DispatcherServlet(中央调度器)↓
【HandlerInterceptor 拦截器】↓
【参数解析器(HandlerMethodArgumentResolver)】↓
Controller 方法执行
🧩 各组件详细解析与执行顺序
1️⃣ Listener
(Servlet Listener)【最早执行】
- 监听整个请求生命周期,例如:
ServletRequestListener
HttpSessionListener
ServletContextListener
- 适合做请求进入/退出日志记录、资源准备等操作
📌【执行时机】:Tomcat 接收到请求,构造 Request
后即触发
2️⃣ Filter
(过滤器)【Servlet 级别】
- 实现
javax.servlet.Filter
接口 - 是整个请求过程中最早的一环,甚至可以不进入 Spring
- 常见用途:登录校验、XSS 过滤、CORS 跨域处理等
📌【执行时机】:
- 在
DispatcherServlet
执行前 - 可通过
FilterRegistrationBean
控制顺序(@Order
或@WebFilter
)
3️⃣ DispatcherServlet
(Spring MVC 核心调度器)
- 核心职责:将请求分发给对应的 Controller
- 执行顺序如下:
DispatcherServlet.doDispatch()├─ 处理 Multipart 请求(如文件上传)├─ 调用 HandlerMapping 查找 Controller├─ 调用 HandlerInterceptor.preHandle()├─ 参数解析器(ArgumentResolver)├─ 调用 Controller 方法├─ HandlerInterceptor.postHandle()└─ 渲染视图(如 JSON、HTML)
4️⃣ HandlerInterceptor
(拦截器)【Spring 层】
- 实现
HandlerInterceptor
接口 - 常用于权限校验、日志记录、参数加工等
- 分为三段生命周期方法:
方法 | 时机 |
---|---|
preHandle | Controller 方法 前 |
postHandle | Controller 方法 后,视图渲染前 |
afterCompletion | 请求全部结束后(包括异常) |
📌【执行时机】:由 Spring MVC 控制,必须经过 DispatcherServlet 才会生效
5️⃣ Aspect
(AOP 切面)【更精细控制】
- 使用
@Aspect
实现 AOP,可以控制更细粒度的方法前后逻辑 - 可用于审计、日志、权限等
📌【执行时机】:真正进入 Controller 方法执行时,环绕通知才会生效
- 与拦截器的最大区别是,它操作的是方法级别,支持注解切点、参数切点等
- 可以作用于 Service、Mapper、Controller 等层面
6️⃣ HandlerMethodArgumentResolver
(参数解析器)
- 将 HTTP 参数解析为 Java 方法参数
- 常见的如
@RequestParam
,@PathVariable
,@RequestBody
就是由这些解析器完成的
7️⃣ Controller
方法执行
至此,请求真正进入你的业务方法。
🧯 异常处理(ExceptionResolver)
- 如果 Controller 或任何处理过程中抛出异常,会进入
HandlerExceptionResolver
- Spring 默认提供:
DefaultHandlerExceptionResolver
ResponseStatusExceptionResolver
ExceptionHandlerExceptionResolver
(处理@ExceptionHandler
注解的方法)
📌 总结执行顺序一览
执行阶段 | 说明 |
---|---|
Listener | 请求刚进来,监听请求/会话/上下文 |
Filter | Servlet 层面统一过滤 |
DispatcherServlet | Spring MVC 核心分发器 |
Interceptor.preHandle | 控制器方法执行前,适合权限校验 |
ArgumentResolver | 将参数注入到 Controller 方法中 |
AOP Around | 控制器方法执行前后,可用于埋点日志 |
Controller 方法 | 正式执行业务代码 |
Interceptor.postHandle | 方法执行后,视图渲染前 |
Interceptor.afterCompletion | 全流程结束后调用,包括异常情况 |
ExceptionResolver | 统一异常处理 |
✅ Filter、Interceptor、AOP 区别总览
对比维度 | Filter | Interceptor(拦截器) | AOP(切面) |
---|---|---|---|
所属技术 | Servlet 规范(JEE 层) | Spring MVC | Spring AOP(基于代理) |
是否依赖 Spring | ❌ 无需依赖 Spring | ✅ 依赖 Spring MVC | ✅ 依赖 Spring(Context + AOP) |
拦截对象 | 所有请求(静态资源也可) | Controller 映射方法(Handler) | Bean 的方法调用 |
拦截级别 | HTTP 请求级别 | MVC 控制器调用前后 | 方法级别(可拦 Service、DAO、Controller) |
是否感知注解 | ❌ 无 | ✅ 可以读取注解 | ✅ 强大注解支持 |
常见应用 | 日志打印、CORS、XSS、限流等 | 登录鉴权、权限控制、日志追踪等 | 审计日志、事务控制、性能统计、通用逻辑抽取 |
是否支持链式调用 | ✅ FilterChain | ✅ 多个拦截器链 | ✅ 多个切面 + 顺序控制(@Order) |
注册方式 | Web.xml 或 Spring Boot 注册 Bean | 实现接口 + WebMvcConfigurer 注册 | @Aspect 注解 + @EnableAspectJAutoProxy |
可用于非 Spring | ✅ 是(纯 Servlet 容器可用) | ❌ 否(只能在 Spring MVC 项目) | ❌ 否(必须由 Spring 管理的 Bean) |
📦 Filter 注册方式(Spring Boot)
方式 1:使用 @WebFilter
注解 + @ServletComponentScan
@WebFilter(urlPatterns = "/*", filterName = "logFilter")
public class LogFilter implements Filter {public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {// 前置处理chain.doFilter(request, response); // 放行// 后置处理}
}
需要在配置类或主启动类上添加:
@ServletComponentScan
方式 2:使用 Spring Boot 的 FilterRegistrationBean
@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<LogFilter> logFilter() {FilterRegistrationBean<LogFilter> bean = new FilterRegistrationBean<>();bean.setFilter(new LogFilter());bean.addUrlPatterns("/*");bean.setOrder(1); // 控制执行顺序,值越小越先执行return bean;}
}
🔗 Interceptor 注册方式(Spring Boot)
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") // 拦截路径.excludePathPatterns("/login"); // 排除路径}
}
拦截器实现:
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 登录校验逻辑return true; // true 放行,false 拦截}
}
🔍 AOP 使用与示例
AOP 切面适用于方法级别的增强操作,比如审计日志、数据脱敏、方法耗时统计等。
1. 添加依赖(如果是 Spring Boot 默认 Web 项目已经包含)
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. 定义切面类
@Aspect
@Component
public class LogAspect {@Pointcut("execution(* com.example.controller..*(..))")public void controllerMethods() {}@Before("controllerMethods()")public void beforeAdvice(JoinPoint joinPoint) {// 打印请求信息}@Around("controllerMethods()")public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {long start = System.currentTimeMillis();Object result = joinPoint.proceed();long end = System.currentTimeMillis();System.out.println("执行耗时:" + (end - start));return result;}
}
📌 执行顺序对比总结(默认情况)
↓ 请求进入 ↓
1. Listener(Servlet 容器级别)
2. Filter(全局过滤,早于 Spring)
3. DispatcherServlet
4. Interceptor.preHandle(Spring 拦截器)
5. AOP @Before / @Around(方法增强)
6. Controller 执行
7. AOP @After / @AfterReturning / @AfterThrowing
8. Interceptor.postHandle
9. Interceptor.afterCompletion
🎯 使用建议
目标 | 推荐使用 |
---|---|
全局过滤如跨域、XSS、编码等 | Filter |
登录认证、权限控制 | Interceptor |
方法日志、埋点、性能统计 | AOP |
文件上传前置处理、敏感词替换等 | Filter 或 AOP(配合注解) |
接口日志记录、签名校验 | Interceptor 或 AOP |