第9课的目标,从来不是教你"写几个异常类"。
而是:在你的后端工程中,亲手搭建一套
👉 可扩展、可定位、可治理的稳定性底座。
从这一课开始,你写的不再只是功能代码,
而是在搭一套系统工程能力。
如果用 Android 来类比,这一课本质上是在后端项目中建立:
- BaseResponse
- 全局异常处理
- 拦截器 / Filter
- 统一日志与 requestId
也就是:后端的 base / core 模块(Infrastructure)。
一、第9课在整套 24 课体系中的真实位置
在前 8 课,你已经完成了:
- 分层架构(interfaces / application / domain / infrastructure)
- ORM、事务、Service 编排
但到目前为止,你的系统还不具备"工程稳定性"。
👉 第9课的角色是:
给整个系统安装"神经系统 + 黑匣子 + 保险丝"。
它直接支撑后续:
- 第10课 Controller 规范
- 第11课 接口质量工程
- 第12课 登录与身份系统
所以,第9课不在业务层,而在:
Infrastructure ------ 基础设施层 / 工程底座
二、Infrastructure 是什么?(Android 视角最容易懂)
Infrastructure = 业务无关 + 全局复用 + 系统级能力
就像 Android 里的 base 模块:
- BaseActivity / BaseResponse
- 网络拦截器
- 全局异常
- 日志、埋点、trace
在后端里,它对应的就是:
- 统一返回体 Result
- 错误码体系 ErrorCode
- 业务异常 BizException
- 全局异常处理器
- requestId / traceId
- 日志规范 / Filter / AOP
👉 它不解决"业务",
👉 它决定"系统怎么活"。
三、第9课实战目标(必须形成的工程闭环)
完成这一课,你的工程中必须出现:
- ✅ infrastructure/common 基础模块
- ✅ 统一异常体系(业务失败 + 系统事故)
- ✅ 统一返回体
- ✅ requestId 全链路
- ✅ 日志分层规范
- ✅ 线上问题可反向定位能力
这是后续所有系统能力的地基。
四、工程落位(基础设施层包结构)
infrastructure
└── common
├── result // 统一返回体(BaseResponse)
├── error // 错误码体系
├── exception // BizException / GlobalHandler
├── web // Filter / Interceptor
├── log // 日志规范 / AOP(扩展)
└── util
👉 这一整块,就是你项目的"base 模块"。
五、异常体系骨架(系统的失败模型)
1️⃣ 统一返回体 Result
java
public class Result<T> {
private boolean success;
private String code;
private String message;
private T data;
private String requestId;
}
👉 所有接口输出统一,所有失败工程化。
2️⃣ 错误码体系 ErrorCode
java
public interface ErrorCode {
String code();
String message();
}
java
public enum UserErrorCode implements ErrorCode {
USER_NOT_FOUND("U_404", "用户不存在"),
PHONE_EXISTS("U_409", "手机号已注册");
}
java
public enum SystemErrorCode implements ErrorCode {
SYSTEM_ERROR("SYS_500", "系统繁忙"),
UNAUTHORIZED("SYS_401", "未登录"),
FORBIDDEN("SYS_403", "无权限");
}
👉 错误不是字符串,是系统语义。
3️⃣ 业务异常 BizException
java
public class BizException extends RuntimeException {
private final String code;
public BizException(ErrorCode errorCode) {
super(errorCode.message());
this.code = errorCode.code();
}
public String getCode() {
return code;
}
}
使用:
java
if (!userExists) {
throw new BizException(UserErrorCode.USER_NOT_FOUND);
}
👉 业务层只描述"失败",不处理失败。
4️⃣ 全局异常出口 GlobalExceptionHandler
java
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BizException.class)
public Result<Void> handleBiz(BizException e) {
log.warn("biz error: {}", e.getMessage());
return Result.fail(e.getCode(), e.getMessage(), RequestId.get());
}
@ExceptionHandler(Exception.class)
public Result<Void> handleSystem(Exception e) {
log.error("system error", e);
return Result.fail("SYS_500", "系统繁忙", RequestId.get());
}
}
👉 所有异常,在这里结束。
六、日志体系骨架(系统的黑匣子)
1️⃣ requestId(每个请求的"案号")
java
public class RequestIdFilter implements Filter {
public void doFilter(...) {
String requestId = UUID.randomUUID().toString();
MDC.put("requestId", requestId);
chain.doFilter(request, response);
MDC.clear();
}
}
logback:
java
requestId=%X{requestId}
👉 所有日志自动带 requestId。
2️⃣ 日志分层原则
- Controller:接口入口 / 参数 / 耗时
- Application:业务流程 / 编排
- Domain:关键业务决策
- Infrastructure:IO / DB / MQ
- ExceptionHandler:事故日志
错误日志必须能回答:
👉 谁 → 干了什么 → 为什么失败 → 关键数据
七、最小工程闭环示例
Controller:
java
@PostMapping("/users")
public Result<UserDTO> register(@RequestBody RegisterReq req) {
return Result.ok(service.register(req), RequestId.get());
}
Domain / Application:
java
if (repo.exists(phone)) {
throw new BizException(UserErrorCode.PHONE_EXISTS);
}
异常 → GlobalHandler → Result → requestId → 日志定位
👉 至此,第9课工程闭环成立。
八、第9课完成标准(极其重要)
当你满足下面 6 条,你这一课才算真正完成:
- ✅ infrastructure/common 独立存在
- ✅ 项目中几乎没有到处 try-catch
- ✅ 所有业务失败统一 BizException
- ✅ 所有未知失败统一 system error
- ✅ 所有日志带 requestId
- ✅ 报错可以反向还原一次请求
九、第9课对你能力层级的意义
从这一课开始,你已经不再是:
❌ 写接口的人
而是在做:
✅ 系统稳定机制设计
✅ 工程底座搭建
✅ 事故可治理能力
你已经站在架构能力起点了。
十、总结
真正稳定的系统,不是从不出错,
而是出错时,依然可控、可查、可修。
第9课搭的不是异常类,
是一套系统的"生命线"。