952 字
约 3 分钟
5
S07-B04 · Spring MVC:一个请求走过哪些组件

适用读者:写过 Controller 但说不清"过滤器与拦截器谁先"的人。
前置:S07-B01。
实测环境:Spring Boot 3.3.6 / JDK 17(2026-11-05)。
覆盖旧文:2619(139) 982(84) 978(72) 984(82) 1740(74) 983(70) 1558(128) = 649 点。
覆盖扩展:E-S07-007(DispatcherServlet 与九大组件)。
上一篇:S07-B03 · AOP:切面、代理与失效场景
下一篇:S07-B05 · 自动配置与启动。


1. 一句话结论

请求先过 Servlet 过滤器(Filter),再进 DispatcherServlet,然后由拦截器(Interceptor)→ Controller → 返回值处理 → 异常解析走完。 顺序是硬性的,记住它就能定位"该在哪一层做校验/日志"。

实测(一次 GET 请求的日志顺序):

[1] Filter.doFilter 前
[2] Interceptor.preHandle
[3] Controller 执行
[4] Interceptor.afterCompletion
[5] Filter.doFilter 后

2. 完整链路(E-S07-007)

Tomcat → Filter 链 → DispatcherServlet
          ├─ HandlerMapping(找到 Controller 方法)
          ├─ HandlerInterceptor.preHandle
          ├─ HandlerAdapter(参数解析 + 调用)
          ├─ 返回值处理(@ResponseBody → HttpMessageConverter)
          ├─ HandlerInterceptor.postHandle
          ├─ 视图渲染(非 @ResponseBody 时)
          ├─ HandlerInterceptor.afterCompletion
          └─ Filter 后置逻辑
异常分支 → HandlerExceptionResolver(@ControllerAdvice)
组件 职责
HandlerMapping URL → 处理方法
HandlerAdapter 参数绑定、反射调用
HttpMessageConverter JSON ↔ 对象(Jackson)
HandlerExceptionResolver 异常 → 响应

3. Filter vs Interceptor vs Listener(A-984/A-1740)

维度 Filter Interceptor Listener
所属规范 Servlet Spring MVC Servlet
能否拿到 Bean 需注入技巧 ✅ 天然是 Bean 需注意
能否拿到处理方法信息 ❌ ✅(HandlerMethod) ❌
典型用途 编码、CORS、请求体包装 登录校验、日志、权限 启动/会话事件

判据:

需要"改请求/响应体"或"在 Spring 之前"处理 → Filter
需要"知道是哪个 Controller 方法" → Interceptor
需要"应用/会话生命周期事件" → Listener

实测顺序:Filter 包着 Interceptor([1] 最外,[5] 最外收尾)。


4. 参数绑定与校验

场景 注解
路径变量 @PathVariable
查询参数 @RequestParam
请求体 JSON @RequestBody + @Valid
表单 @ModelAttribute
头/Cookie @RequestHeader / @CookieValue

实测(校验失败):

[HTTP 400] {"errors":[{"msg":"must not be blank","field":"name"},
                      {"msg":"must be less than or equal to 120","field":"age"}]}

Spring 对 @Valid 失败默认抛 MethodArgumentNotValidException(→ 400),需要 @RestControllerAdvice 转成统一结构(B06)。


5. 三层架构(A-978)

层 职责 不该做什么
Controller 参数校验、编排、返回 写业务逻辑、直接写 SQL
Service 业务规则、事务边界 处理 HTTP 细节
Repository/Mapper 数据访问 业务判断

判据:"这段逻辑换成 CLI 调用还需要吗?" 需要 → 应该在 Service。


6. 五个误区

误区 真相
"拦截器比过滤器早" Filter 在最外层
"Filter 里能拿到 Controller 方法" 不能(Interceptor 才能)
"@Valid 失败返回 500" 返回 400(MethodArgumentNotValidException)
"Controller 可以写业务逻辑" 会导致无法复用、难测试
"@ResponseBody 也要视图解析" 不走视图,走 HttpMessageConverter

7. 自检

  1. 一次请求的五步顺序(实测)?
  2. Filter 与 Interceptor 的三点差异?
  3. 什么时候必须用 Filter 而不是 Interceptor?
  4. @Valid 失败默认抛什么异常、返回什么状态码?
  5. 三层架构里 Controller 不该做什么?

8. 下一篇

S07-B05 · Spring Boot:自动配置与启动流程

链路讲完,下一篇解释"为什么加个 starter 就有一堆 Bean",以及启动那 8–10 秒花在哪。


本篇属于系列《S07 · Spring 框架》。旧文来源:A-2619/982/978/984/1740/983/1558;扩展点 E-S07-007。Filter/Interceptor 顺序与 400 响应为 Spring Boot 3.3.6 实测。

S07-B04 · Spring MVC:一个请求走过哪些组件
https://www.clxhxhhr.top/posts/5271/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。