统一自定义异常规范的核心是行为一致,需在命名(以Exception结尾、分层继承)、构造(三类构造方法、errorCode字段)、抛出(保留cause根因)、序列化(实现Serializable)和全局处理(@ControllerAdvice返回标准JSON)五环节达成共识。

团队开发中统一自定义异常规范,核心不是写多少类,而是让每个成员抛出、捕获、记录、传递异常时行为一致。重点在命名、继承、构造、携带信息和全局处理五个环节达成共识。
统一命名与继承体系
所有业务异常必须以 Exception 结尾,且按语义分层继承:
- 顶层抽象基类:如
BaseBusinessException,继承RuntimeException,不直接使用 - 领域子类:如
UserException、OrderException、PaymentException,各自封装本域错误码前缀(如USER-404、ORDER-409) - 禁止出现
MyException、ExceptionUtil这类模糊命名;也不允许直接继承Exception(即不强制捕获的受检异常),除非极特殊合规场景
强制构造方法与关键字段
每个自定义异常类必须提供以下构造方式,并默认支持异常链:
- 带错误码和消息的构造方法:
new UserException("USER-404", "用户不存在") - 带消息和原始异常(cause)的构造方法:
new UserException("用户查询失败", e) - 带错误码、消息、原始异常三参数的完整构造方法
- 必须包含
errorCode字段(String 类型,便于前端识别),可选添加businessId(如订单号、用户ID)用于日志追踪
异常抛出与包装必须保留根因
任何 catch 后重新抛出,都必须显式传入 cause,禁用 “吞掉再抛新异常” 写法:
立即学习“Java免费学习笔记(深入)”;
- ✅ 正确:
throw new OrderException("ORDER-500", "库存扣减失败", e); - ❌ 错误:
throw new RuntimeException("库存操作失败");(丢失数据库超时/连接拒绝等根因) - 服务间调用(如 Feign、Dubbo)需确保异常可序列化:实现
Serializable,声明serialVersionUID
配合全局异常处理器落地规范
在 Spring Boot 项目中,统一用 @ControllerAdvice + @ExceptionHandler 拦截所有自定义异常:
- 返回标准 JSON 格式:
{"code": "USER-404", "message": "用户不存在", "timestamp": "..."} - 对非自定义异常(如
NullPointerException)单独归为系统错误,返回通用码如SYS-500,并自动打全量日志(含堆栈) - 日志记录必须包含:
errorCode、businessId(如有)、traceId,方便 ELK 或 SkyWalking 关联排查


















