Feign默认不透传受检异常,需通过统一响应体(200状态码+code/message字段)和自定义ErrorDecoder解析并抛出Runtime异常(如ApiBusinessException),再由调用方try-catch捕获处理。

Feign默认不透传受检异常(Checked Exception),它会把所有HTTP错误响应(4xx/5xx)统一包装成FeignException或其子类(如RetryableException),而原始业务异常(比如服务端抛出的BusinessException)会被序列化为响应体,但不会以Java异常形式抵达调用方。要实现受检异常的语义透传,核心不是“让Feign抛出受检异常”,而是**让服务端异常信息可识别、可解析、可映射为调用方可捕获的统一异常类型**。
服务端统一异常响应体结构
确保被调用服务对所有业务异常返回标准格式的JSON,例如:
- 状态码:始终返回200(避免触发Feign默认错误解码逻辑)
-
响应体:包含
code(业务错误码)、message、data等字段 -
示例:
{"code":40001,"message":"用户不存在","data":null}
自定义Feign ErrorDecoder
编写ErrorDecoder实现类,在decode()方法中解析非200响应(或按需解析200响应中的error字段),并抛出自定义运行时异常(如ApiBusinessException):
- 若服务端对异常仍返回4xx/5xx,直接在
decode()中读取响应体,提取code和message - 若服务端对异常也返回200,则需判断响应体中
code != 0,再构造异常 - 异常类建议继承
RuntimeException,避免强制try-catch,符合Spring生态习惯
Feign配置与全局生效
将自定义ErrorDecoder声明为@Bean,作用域为feign.Client级别或全局:
立即学习“Java免费学习笔记(深入)”;
- 全局生效:在
@Configuration类中定义@Bean public ErrorDecoder errorDecoder(){...} - 指定Client生效:通过
@FeignClient(configuration = MyConfig.class)绑定 - 确保该Bean优先级高于默认
Default实现(通常自动覆盖)
调用方安全捕获与处理
调用方代码无需throws声明,但可通过try-catch捕获你定义的异常类型:
try { userClient.getUser(123); } catch (ApiBusinessException e) { // 处理业务异常 }- 异常对象中应携带
code、message、甚至原始Response供深度诊断 - 配合全局异常处理器(
@RestControllerAdvice),可进一步统一日志与监控埋点


















