核心是重构错误语义表达与传播路径,分四步渐进迁移:识别场景分类错误、建桥接层转化异常、按调用栈分层改造、保留兼容但切断错误传播链。

核心不是“替换返回码”,而是重构错误语义的表达方式和传播路径。旧系统用 int code 或 String msg 表示失败,本质是把错误当成业务数据的一部分;现代异常体系要求错误即异常——可分类、可拦截、可携带上下文、可触发特定恢复逻辑。平滑迁移的关键在于分层解耦、渐进封装、语义对齐,而非一刀切改 throw。
第一步:识别并隔离返回码使用场景
先不改代码,只做归类分析:
- 纯技术失败(如网络超时、数据库连接断开、JSON解析失败)——这类应直接升级为 unchecked 异常,无需业务层判断 code
-
业务规则拒绝(如“余额不足”“库存已售罄”“用户未实名”)——这类需映射为领域语义明确的 checked 或 unchecked 子异常,比如
InsufficientBalanceException -
协议级约定码(如第三方接口返回
code=40001表示签名错误)——保留原始码字段,但包装进自定义异常,避免业务层硬编码数字 -
兜底通用码(如
code=-1或"UNKNOWN_ERROR")——这是重构重点,说明上游缺乏错误分类意识,需推动上游补全语义,或在本层做初步归因(如根据 stack trace 或 response body 关键字 fallback)
第二步:建立统一异常转化桥接层
不追求“一层统管”,而是在关键出入口设轻量桥接:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- HTTP 客户端调用后,用
ResponseEntity<?>或RestTemplate的ResponseErrorHandler捕获响应体,根据 status + body.code 构造对应异常,再抛出,而非返回Result<T>包装体 - DAO 层返回
int updateCount或boolean success的地方,补充校验逻辑:若影响行数为 0 且操作语义应成功(如更新用户状态),主动 throwOptimisticLockException或ResourceNotFoundException - 遗留 Service 方法仍返回
Result<T>?允许短期共存,但新增一个xxxOrFail()同名方法,内部做if (!result.isSuccess()) throw mapToException(result);,逐步引导调用方切换
第三步:按调用栈深度分阶段改造
从底层向上推进,确保每层只承担一类责任:
立即学习“Java免费学习笔记(深入)”;
-
数据访问层:停用
try-catch-return new Result(code, msg),改用 Spring 的DataAccessException体系(如DuplicateKeyException、EmptyResultDataAccessException),让事务、重试、降级策略自然生效 -
服务编排层:不再手动拼装 error code,而是 catch 明确异常类型,做日志增强(如记录被拒的订单 ID、用户 ID)、指标打点(
error_type=insufficient_balance)、或调用补偿服务 -
API 网关/Controller 层:统一用
@ExceptionHandler处理顶层异常,将不同异常映射为标准 HTTP 状态码 + 语义化 error object(含errorCode字段供前端展示,但不再用于逻辑分支)
第四步:保留兼容性,但切断错误传播链
老代码一时无法全量改造?用“异常透传+返回码兜底”过渡:
- 定义一个
LegacyCodeAwareException,带legacyCode和legacyMsg字段,所有桥接层抛出此异常 - 在 Controller 中捕获它,仍可返回旧版 JSON 结构(
{"code": 1001, "msg": "...", "data": null}),但禁止在 service 层再 if (code == 1001) 做分支 - 新功能一律禁用返回码风格,强制使用异常驱动流程,形成“新老并存但不混用”的边界

















