全局异常处理需三步:定义统一result响应结构(含code、msg、data、timestamp),用@restcontrolleradvice捕获异常并按优先级处理,补充参数校验、业务异常、数据库约束等关键能力。

直接上手写一个能跑、能用、上线不翻车的全局异常处理,核心就三件事:定义返回格式、捕获异常类型、区分业务与系统错误。不用堆概念,照着做就能替掉所有 Controller 里的 try-catch。
定义统一响应结构(Result 类)
前端只认一种 JSON 格式,所以先定死结构。推荐包含 code、msg、data 和 timestamp 四个字段,避免后期加字段改全量接口。
- code 用 Integer 类型,方便扩展业务码(如 1001=用户不存在,4001=手机号已注册)
- msg 是面向用户的提示语,别暴露技术细节(比如不写“NullPointerException”,而写“请求参数有误”)
- timestamp 建议保留,生产排查时能精准对齐日志时间
- 提供 success() 和 error(code, msg) 两个静态工厂方法,Controller 层调用清爽
编写全局异常处理器(@RestControllerAdvice)
这个类是真正的“异常收口”,Spring Boot 会自动扫描并拦截所有 @RestController 方法抛出的异常。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 用 @RestControllerAdvice(不是 @ControllerAdvice),确保返回值自动转 JSON
- @ExceptionHandler 注解要按优先级顺序写:先捕获具体异常(如 MethodArgumentNotValidException),再捕获通用业务异常(如 BusinessException),最后兜底 Exception
- 每个处理方法里必须记录日志,建议用 log.error("业务异常", e),而不是 e.printStackTrace()
- 对数据库约束异常(如 DataIntegrityViolationException)要做翻译,把“Duplicate entry”转成“手机号已被注册”这类可读提示
补充关键能力(让异常处理真正落地)
光能捕获还不够,实战中还要解决几个高频问题:
- 参数校验失败要自动提取字段名和错误信息,别只返回“校验失败”。捕获 MethodArgumentNotValidException 后,遍历 getFieldErrors() 拼装成 {“mobile”: “手机号格式错误”} 结构
- 自定义业务异常类(如 BusinessException)必须带 error code 和 message 构造器,且继承 RuntimeException,保证事务能正常回滚
- 开发环境可返回 stackTrace,生产环境一律屏蔽——用 @Profile("dev") 配合 @JsonInclude(JsonInclude.Include.NON_NULL) 控制序列化字段
- 如果用了 Feign 或 OpenFeign,记得在 fallback 中也复用同一套 Result 格式,前后端体验才一致
写完测试几个典型场景:空指针、参数校验失败、手动 throw BusinessException、数据库唯一键冲突。只要返回都是 {“code”:xxx, “msg”:”xxx”, “data”:null, “timestamp”:xxx},就说明成了。










