1047 字
约 3 分钟
6
S07-B06 · Web 层实战:校验、异常、日志、文档、监控

适用读者:要把一个接口"做完整"的人。
前置:S07-B04、S07-B05。
实测环境:Spring Boot 3.3.6 / JDK 17(2026-11-05)。
覆盖旧文:327(77) 330(58) 328(57) 326(61) 324(58) 493(37) 1746(82) 1754(101) 505(37) 473(40) 1755(66) 401(628) = 1,302 点。
覆盖扩展:E-S07-010(统一响应与全局异常)。
上一篇:S07-B05 · Spring Boot:自动配置与启动流程
下一篇:S07-J01 · 事务传播与失效。


1. 一句话结论

一个"能上线"的接口需要五件套:参数校验、统一响应、全局异常、可追踪日志、可查的文档/监控。缺一个,线上就会以某种方式咬你。

组件 缺失后果
参数校验 脏数据进库
统一响应 前端要兼容多种结构
全局异常 500 带堆栈泄露
链路日志 排障时找不到一次请求的完整日志
文档/监控 联调靠猜、故障靠用户反馈

2. 实测:校验失败返回什么

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

对比 S10(FastAPI):FastAPI 返回 422,Spring 返回 400——两者语义都指"请求不合法",但前端要按框架区分(跨语言服务共存时要统一)。

合法请求:

[HTTP 201] {"age":30,"name":"张三"}

3. 统一响应 + 全局异常(E-S07-010)

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<?> onInvalid(MethodArgumentNotValidException e) {
        var errs = e.getBindingResult().getFieldErrors().stream()
            .map(f -> Map.of("field", f.getField(), "msg", f.getDefaultMessage())).toList();
        return ResponseEntity.badRequest().body(Map.of("errors", errs));
    }
}
原则 说明
不返回堆栈 泄露内部结构
错误码可区分 业务码 + HTTP 状态码双轨
字段级错误 前端能定位到具体字段

实测:上面那段 @RestControllerAdvice 就是产出 §2 那段 JSON 的代码。


4. 日志:MDC 链路追踪(A-326/A-324/A-493)

MDC.put("traceId", UUID.randomUUID().toString().substring(0, 8));
try { /* 业务 */ } finally { MDC.clear(); }     // ← 必须清理(线程池!)
点 说明
logback-spring.xml 在 pattern 里加 %X{traceId}
线程池 不清理会串号(同 S05-B04 的 ThreadLocal 泄漏)
异步任务 要显式传递 MDC(TaskDecorator)

判据:"能在一次请求的所有日志里 grep 到同一个 traceId 吗?" 不能 → 链路日志没做好。


5. 文档与监控(A-1754/A-505/A-473)

工具 用途 注意
springdoc-openapi 生成 OpenAPI(Swagger UI 的现代替代) Spring Boot 3 用 springdoc-openapi-starter-webmvc-ui
Knife4j 增强 UI 与 springdoc 版本要匹配
Spring Boot Admin 多实例监控面板 需要 actuator
Actuator 健康/指标/环境 生产要限制端点暴露

安全提醒:management.endpoints.web.exposure.include=* 在生产等于把内部信息公网暴露。


6. HTTP 客户端:RestTemplate(A-401,628 点)

客户端 状态
RestTemplate 维护模式(仍可用)
WebClient 响应式推荐
RestClient(Boot 3.2+) 同步场景的新推荐

判据:新项目同步调用用 RestClient;已在 WebFlux 栈用 WebClient;老项目继续 RestTemplate。


7. 五个误区

误区 真相
"全局异常处理只是少写 try-catch" 它决定对外错误契约
"MDC 会自动清理" 线程池必须手动
"Swagger UI 直接上生产" 会暴露接口全貌,需鉴权
"actuator 全开更方便" 泄露环境/配置
"Spring 与 FastAPI 错误码一致" 400 vs 422(实测)

8. 自检

  1. "能上线的接口五件套"是什么?
  2. Spring 的 @Valid 失败返回什么状态码?FastAPI 呢?
  3. 全局异常处理的三条原则?
  4. MDC 为什么必须清理?异步任务怎么传?
  5. 生产环境 actuator 该怎么配?

9. 下一篇

S07-J01 · 事务:传播机制与失效的六种原因

基础层到此结束。进阶层第一篇讲 Spring 最容易被讲成玄学的部分:事务为什么"不生效"。


本篇属于系列《S07 · Spring 框架》。旧文来源:A-327/330/328/326/324/493/1746/1754/505/473/1755/401;扩展点 E-S07-010。400/201 响应为 Spring Boot 3.3.6 实测。

S07-B06 · Web 层实战:校验、异常、日志、文档、监控
https://www.clxhxhhr.top/posts/5273/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。