应统一拦截非受检异常并返回结构化错误响应,含code、message、traceId;前端依code分级提示;关键位置主动校验防异常;全链路traceId日志闭环。

在客户端调用(如前端 JavaScript 调用后端 API,或移动端调用服务接口)时,非受检运行期异常(如 NullPointerException、IllegalArgumentException、RuntimeException 及其子类)通常不会被编译器强制处理,但一旦发生,往往导致接口返回 500、空响应、或格式错乱的错误体,使前端无法稳定解析和友好提示。
统一异常拦截与结构化错误响应
后端应避免让未捕获的运行期异常直接穿透到容器(如 Tomcat)返回原始堆栈页。推荐使用全局异常处理器统一拦截:
- Spring Boot 中用
@ControllerAdvice + @ExceptionHandler(RuntimeException.class)捕获所有非受检异常 - 返回标准化 JSON 错误体,包含
code(业务码,如"INTERNAL_ERROR")、message(面向用户/开发者的简明提示)、traceId(用于日志追踪) - 对敏感信息做脱敏:不暴露类名、文件路径、数据库语句等,
message应是预设的友好文案,而非e.getMessage()原始值
前端按错误码分级提示,而非依赖 HTTP 状态码
不要仅靠 response.status !== 200 判断失败——很多业务异常仍返回 200(如 RESTful 设计中“成功响应但操作未达成”),而部分 500 错误可能已由网关兜底转为 4xx。应约定:
- 响应体始终含
success: boolean或code字段,以它为准判断成败 - 前端建立错误码映射表:
"VALIDATION_FAILED" → "请检查输入内容","RESOURCE_NOT_FOUND" → "请求的数据不存在" - 对
"INTERNAL_ERROR"等系统级错误,显示通用提示(如“服务暂时不可用,请稍后重试”),并自动上报traceId到监控平台
关键位置主动防御,把运行期异常转为可预期的业务异常
与其被动捕获 NullPointerException,不如在入口处主动校验:
- 用
@NotNull、@NotBlank等注解 +@Valid触发参数校验,失败时抛MethodArgumentNotValidException(可被统一拦截为"VALIDATION_FAILED") - 对可能为空的外部数据(如第三方 API 返回、缓存读取结果),显式判空并抛出带语义的业务异常:
throw new BusinessException("USER_PROFILE_MISSING", "用户资料未完善") - 数据库查询结果为
null时,不直接调用user.getName().length(),而是先检查再操作,或用Optional封装并定义缺失场景行为
日志与可观测性闭环
优雅提示的前提是快速定位问题。需确保:
- 每个异常被捕获时,记录完整上下文:traceId、入参摘要、执行路径、异常类型和精简消息(不打堆栈全量)
- 前端在报错时,将当前 traceId、时间、设备信息、操作步骤(可选)一并发送至前端监控服务
- 建立 traceId 关联:从前端错误上报 → 网关日志 → 后端应用日志 → 数据库慢查,形成可追溯链路
不复杂但容易忽略:真正的“优雅”不是让错误不发生,而是让错误发生时,用户不困惑、开发者不抓瞎、问题不隐身。

















