问题描述
项目环境:
JDK 17Spring Boot 3.0.4Dubbo 3.2.0-beta.3Spring Cloud 2022.0.0Spring Cloud Alibaba 2022.0.0.0-RC1
最近在学习Dubbo的时候,按照之前的习惯定义了自定义异常和统一异常处理,但是在进行接口测试的时候,发现并不是自定义的异常处理,而是被当做系统异常进行了处理。
出现原因
经过搜索之后发现,dubbo提供了异常处理的类ExceptionFilter(org.apache.dubbo.rpc.filter.ExceptionFilter),大概功能就是对指定的一些异常放行,然后其他异常统一包装成RuntimeException返回。所以在异常处理的时候会按照 RuntimeException 进行处理。
解决方案
所以按照网上的方案,重写一个过滤器,让异常通过我们自己实现的过滤器,这样就可以对自定义异常进行放行处理。 网上常见的方法是新建一个 Filter 类,继承 ExceptionFilter 类,重写 invoke()方法。然后新增配置,大概参考这篇博客,: https://www.cnblogs.com/fnlingnzb-learner/p/16810063.html
但是按照这样实现之后,自定义异常仍然不能被正常处理,所以就开始继续debug。
问题分析
在经过debug和源码的阅读之后发现,虽然异常进入了自己写的过滤器,但是最后还是会回到 ExceptionFilter 类中的 onResponse() 方法中去,并且也是在这里被包装成 RuntimeException 所以大概是 Dubbo 3 修改了很多源码(回过头发现和之前网上的解决方案中的源码确实不同),导致之前的写法不能生效了,所以最后在自定义过滤器中重写了 onResponse() 方法,测试发现可以正常进行自定义异常的处理了。
完整解决方案
新建 DubboExceptionFilter 类,注意修改内容
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.filter.ExceptionFilter;
@Activate(group = CommonConstants.PROVIDER)
public class DubboExceptionFilter extends ExceptionFilter {
@Override
public void onResponse(Result appResponse, Invoker> invoker, Invocation invocation) {
// 如果有异常
if (appResponse.hasException() && GenericService.class != invoker.getInterface()) {
// 获取抛出的异常
Throwable exception = appResponse.getException();
String classname = exception.getClass().getName();
// 如果是自定义异常,直接抛出
if (classname.startsWith("top.flobby.live.common.exception")) {
return;
}
// 如果是其他异常,使用Dubbo的业务进行处理
super.onResponse(appResponse, invoker, invocation);
}
}
}
resources目录下新建META-INF/dubbo/com.alibaba.dubbo.rpc.Filter = 前面的只是一个表示,叫什么都可以 = 后面的是刚刚新建的过滤器全路径
DubboExceptionFilter=xxx.xxx.filter.DubboExceptionFilter
对应的Dubbo服务提供者的配置文件新增以下内容,这里是yml格式
dubbo:
... 其他配置
provider:
filter: DubboExceptionFilter,-exception
效果展示
文章来源
发表评论