核心是统一异常语义、结构和使用方式,通过分层基类(BaseException、BusinessException等)、5位错误码规范(如B0023)、标准构造方法及上下文注入(requestId、userId等),实现异常可读、可追踪、可协作;Controller统一拦截转JSON,Service只抛业务异常,严禁滥用。

核心是统一异常语义、结构和使用方式,让错误成为可读、可追踪、可协作的业务语言,而不是零散的日志或模糊提示。
定义分层异常基类
建立清晰的继承体系,避免所有异常都继承 RuntimeException 或 Exception:
- 创建抽象基类 BaseException,封装通用字段:错误码(ErrorCode)、请求ID、上下文 Map、时间戳
- 派生三类顶层异常:BusinessException(业务规则失败,如库存不足)、SystemException(技术故障,如 DB 连接超时)、ExternalServiceException(第三方调用异常)
- 禁止直接 throw new RuntimeException("xxx") —— 所有业务错误必须走 BusinessException 及其子类
强制错误码与命名规范
错误码不是随意编号,而是团队协作的契约:
- 采用 5 位字符串格式,如 B0023:首字母表示来源(A=用户输入,B=本系统,C=第三方),后四位数字按模块顺序分配
- 异常类名必须以 Exception 结尾,且体现业务域,例如 InventoryShortageException、CouponExpiredException
- 每个错误码在项目 Wiki 或内部平台有唯一释义,包含:触发条件、影响范围、建议动作(如“重试”或“联系运营”)
统一构造与上下文注入方式
确保每次抛出异常都携带可诊断信息,而非仅靠 message 字符串:
立即学习“Java免费学习笔记(深入)”;
- 所有自定义异常提供标准构造方法:(ErrorCode, String message, Map<String, Object> context, Throwable cause)
- 上下文必须包含至少三项关键字段:requestId(全链路追踪)、userId(定位主体)、orderId 或类似业务主键(关联实体)
- 禁止在 catch 块中吞掉原始异常;需用 cause 参数保留栈轨迹,形成异常链
约束异常使用场景与传播边界
防止异常滥用或误用,明确“谁该抛、谁该捕、谁该转”:
- Controller 层统一拦截 BaseException 子类,转为标准化 JSON 响应(含 error_code、message、details)
- Service 层只抛出业务异常,不处理;技术异常(如 SQLException)应被包装为 SystemException 后再向上抛
- 禁止在循环、getter、toString 等非关键路径中主动 throw 异常;异常只用于真正中断流程的业务失败点


















