spring boot 多层级异常分流处理的核心是按职责分层:接口层处理请求合规性异常,业务层用自定义 businessexception 显式抛出规则类异常,数据层异常包装为 dataaccessexception,系统层兜底未捕获异常;通过 @restcontrolleradvice + 多个 @exceptionhandler 实现“一类一策”,统一返回 result 结构、分级日志(warn/error)与 traceid 全链路追踪;service 层只抛不捕,确保异常上浮至全局处理器。

Spring Boot 中实现多层级异常分流处理,核心是让不同来源、不同性质的异常各归其位、各走其道,避免“一锅煮”或层层 try-catch。关键不在于捕获得多,而在于分得清、理得顺、响应得准。
按分层职责明确异常归属
先划清边界:接口层管请求合规性,业务层管规则合理性,数据层管操作可行性,系统层兜底不可预知问题。
- 接口层异常(如参数校验失败、HTTP 方法错误)→ 由 Spring MVC 内置解析器自动触发,比如
MethodArgumentNotValidException、HttpRequestMethodNotSupportedException - 业务层异常(如“余额不足”“订单已取消”)→ 必须用自定义异常(如
BusinessException)显式抛出,禁止混用RuntimeException - 数据层异常(如主键冲突、连接超时)→ 通常包装为
DataAccessException子类,可统一拦截并转为业务语义错误 - 未被捕获的系统异常(如空指针、OOM)→ 兜底交给全局处理器,记录完整堆栈但绝不暴露给前端
用 @ControllerAdvice 实现精准分流
一个 @RestControllerAdvice 类内,通过多个 @ExceptionHandler 方法分别匹配不同异常类型,实现“一类一策”:
- 处理业务异常:
@ExceptionHandler(BusinessException.class)→ 返回Result.fail(ex.getCode(), ex.getMessage()),状态码用 4xx(如 400/403/404) - 处理参数校验异常:
@ExceptionHandler(MethodArgumentNotValidException.class)→ 提取BindingResult中的字段错误,组装成结构化提示(如{"username": "用户名不能为空"}) - 处理远程调用异常:
@ExceptionHandler(FeignException.class)→ 判断 HTTP 状态码,区分是服务不可用(503)还是业务拒绝(4xx),并添加重试建议头 - 兜底处理:
@ExceptionHandler(Exception.class)→ 记录 ERROR 日志(含 traceId、请求路径、参数摘要),返回通用 500 响应,不带堆栈
配合统一响应与日志上下文
分流之后,响应格式和日志记录要同步升级,否则“分了也白分”:
- 所有异常处理器都返回同一套
Result<t></t>结构,前端无需判断响应形态 - 每个异常处理方法中主动写日志,用
log.warn()记业务异常(含用户ID、订单号等上下文),用log.error()记系统异常(附带完整e.printStackTrace()) - 在 WebMvcConfigurer 中注册
HandlerInterceptor,为每次请求生成唯一traceId并存入 MDC,确保日志可全链路追溯
Service 层只抛不捕,保持异常上浮通畅
这是分流能落地的前提——业务逻辑里不要用 try-catch 吞掉异常,而是让异常自然冒泡到 Controller 层,交由全局处理器统一调度:
- DAO 方法抛出
DataAccessException,Service 不捕获,直接向上抛或转为BusinessException - Service 方法校验失败时,直接
throw new BusinessException(400, "手机号格式错误"),不自己构造返回对象 - Controller 方法签名不声明
throws,靠全局处理器接管,代码干净无干扰











