Dubbo中自定义受检异常默认被包装为RpcException,透传需继承RuntimeException或配置exception-classes白名单(3.2+),禁用包装不推荐;异常类须Serializable且Consumer端需存在该类。

在 Dubbo 中,服务接口方法若声明 throws 自定义受检异常(checked exception),默认会被 RpcException 包装并抛出,导致调用方无法直接捕获原始异常类型。要让自定义受检异常“透传”到消费者端,关键在于 **避免 Dubbo 的异常拦截机制将其转为 RpcException**,核心手段是:**不将异常声明为受检异常(即不继承 Exception),或通过配置显式放行特定异常类型**。
方式一:改用运行时异常(推荐)
Dubbo 默认只对继承自 Exception 但非 RuntimeException 的异常做包装。因此最简单可靠的方式是让自定义异常继承 RuntimeException:
- 修改异常类,不再 extends
Exception,而是 extendsRuntimeException - 接口方法仍可声明
throws MyBizException(语法允许,且语义更清晰) - Provider 抛出该异常后,Consumer 端能原样捕获,类型一致、堆栈完整
示例:
public class OrderNotFoundException extends RuntimeException { /* ... */ }
// 接口
public interface OrderService {
Order queryOrder(Long id) throws OrderNotFoundException;
}方式二:配置异常白名单(Dubbo 3.2+)
从 Dubbo 3.2.0 开始,支持通过 dubbo.application.throw-exception-on-error 和 dubbo.application.exception-classes 控制异常透传:
立即学习“Java免费学习笔记(深入)”;
- 在 Provider 的
dubbo.properties或 Spring Boot 配置中添加:dubbo.application.exception-classes=com.example.MyBizException,com.example.OtherException - 确保这些异常类在 Provider 和 Consumer 端类路径中都存在且全限定名一致
- 此时即使它们是受检异常,Dubbo 也会跳过包装,直接序列化传递
方式三:禁用异常包装(不推荐)
全局关闭异常包装虽可行,但会丢失 Dubbo 对网络、协议等底层异常的统一处理能力:
- 设置
dubbo.application.throw-exception-on-error=false - 所有异常(包括
IOException、TimeoutException)都不再被包装为RpcException - Consumer 需自行区分业务异常与系统异常,维护成本高,易出错
注意事项
无论采用哪种方式,都要确保:
- 自定义异常类必须实现
Serializable,且最好有无参构造函数和String message构造函数 - Consumer 端类路径中必须存在该异常类,否则反序列化失败会降级为
RuntimeException - Dubbo 2.x 版本不支持
exception-classes白名单,只能用方式一或方式三


















