Java优雅异常体系核心是错误可识别、分类、追溯、翻译,通过分段式错误码枚举(含编码、描述、状态码等)、轻量BizException基类、@ControllerAdvice全局处理器及配套规范(登记表、代码模板、文档聚合、CI拦截)实现。

Java 中设计优雅的异常错误码枚举与业务异常体系,核心是让错误可识别、可分类、可追溯、可翻译,同时避免硬编码字符串和魔法数字,兼顾开发体验与线上运维能力。
错误码枚举:结构清晰、职责单一
错误码不应只是简单的一组常量,而应是一个有语义、可扩展、带元信息的枚举。推荐包含:唯一编码(String 或 long)、业务模块标识、简明中文描述、HTTP 状态码(如适用)、是否可被前端直接展示等字段。
- 编码建议采用分段式命名,如 "USER_001"(模块_序号)或 "AUTH_LOGIN_FAILED",避免纯数字(如 1001),便于搜索和理解
- 每个枚举项封装完整错误上下文,例如:USER_NOT_FOUND("USER_001", "用户不存在", HttpStatus.NOT_FOUND, true)
- 提供根据 code 查找枚举实例的静态方法(
of(String code)),方便运行时解析 - 可考虑实现
ErrorCode接口,统一抽象,为未来接入国际化或多语言支持留扩展点
业务异常类:轻量、不可忽略、携带上下文
定义一个统一的业务异常基类(如 BizException),继承 RuntimeException,构造时强制传入错误码枚举,并支持附加动态参数(如用户名、ID)用于日志和提示拼接。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 不建议每种错误都新建一个异常类(如
UserNotFoundException),除非需特殊处理逻辑;多数场景用一个泛型 BizException + 枚举即可 - 异常对象应持有原始错误码枚举引用,而非仅存字符串,便于反射获取描述、状态码等元数据
- 重写
getMessage()方法,自动将枚举描述 + 动态参数格式化(如"用户 [zhangsan] 不存在"),避免调用方重复拼接 - 可添加
getErrorCode()和getParams()方法,供全局异常处理器提取结构化信息
全局异常处理器:统一拦截、分级响应
使用 @ControllerAdvice 拦截所有控制器抛出的异常,区分系统异常(Exception)、业务异常(BizException)和参数校验异常(MethodArgumentNotValidException)。
立即学习“Java免费学习笔记(深入)”;
- 对
BizException提取错误码、参数、HTTP 状态码,组装标准响应体(如{"code": "USER_001", "msg": "用户不存在", "data": null}) - 对非业务异常(如空指针、数据库连接失败)记录详细日志(含堆栈),返回通用错误码(如
"SYS_500"),不暴露内部细节 - 支持根据请求头(如
Accept-Language)动态选择错误消息语言,底层依赖错误码枚举的多语言资源映射 - 可配合 Spring Boot Actuator 或自定义监控埋点,对高频错误码自动告警
配套工具与规范:让体系真正落地
再好的设计,若缺乏配套支持,容易在团队协作中退化为“摆设”。需配套以下实践:
- 建立错误码登记表(Excel 或 Wiki),记录每个 code 的用途、责任人、变更历史,上线前需评审
- 提供 Lombok 注解或 IDE 插件模板,一键生成 BizException 抛出代码(如
throw BizException.of(USER_NOT_FOUND, username);) - 在 Swagger 或 OpenAPI 文档中,自动聚合所有使用的错误码,生成“错误说明”章节,供前端查阅
- CI 阶段加入检查:禁止在代码中直接 new RuntimeException("xxx") 或写死字符串错误码,通过 PMD/Checkstyle 规则拦截

















