springboot dubbo服务端抛出自定义异常,消费端捕获却是RuntimeException异常

项目场景:

dubbo服务提供端抛出自定义异常BusinessException,消费端捕获后统一封装处理数据。


问题描述:

消费端捕获的异常类却为RuntimeException,根据打印异常信息,发现dubbo服务端自定义异常被封装成RuntimeException后抛出,如下所示:

java.lang.RuntimeException: com.xiaozhou.common.domain.BusinessException: 对不起,您没有权限访问
com.xiaozhou.common.domain.BusinessException: 对不起,您没有权限访问
	at com.xiaozhou.dynamic.api.ArticleApiImpl.queryArticleDtoByAuth(ArticleApiImpl.java:115)
	at org.apache.dubbo.common.bytecode.Wrapper2.invokeMethod(Wrapper2.java)
	at org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:47)
	at org.apache.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:84)
	at org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker.invoke(DelegateProviderMetaDataInvoker.java:56)
	at org.apache.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:56)
	at org.apache.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:55)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
	at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:92)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
	at org.apache.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:48)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
	at org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:81)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
	at com.xiaozhou.dynamic.filter.ExceptionFilter.invoke(ExceptionFilter.java:39)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
	at org.apache.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:96)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
	at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:148)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
	at org.apache.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
	at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:41)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$CallbackRegistrationInvoker.invoke(ProtocolFilterWrapper.java:157)
	at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:152)
	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:102)
	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:193)
	at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:51)
	at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

	at org.apache.dubbo.rpc.filter.ExceptionFilter$ExceptionListener.onResponse(ExceptionFilter.java:105) ~[dubbo-2.7.3.jar:2.7.3]
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$CallbackRegistrationInvoker.lambda$invoke$0(ProtocolFilterWrapper.java:167) ~[dubbo-2.7.3.jar:2.7.3]
	at org.apache.dubbo.rpc.AsyncRpcResult.lambda$whenCompleteWithContext$0(AsyncRpcResult.java:155) ~[dubbo-2.7.3.jar:2.7.3]
	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760) ~[na:1.8.0_202]
	at java.util.concurrent.CompletableFuture.uniWhenCompleteStage(CompletableFuture.java:778) ~[na:1.8.0_202]
	at java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:2140) ~[na:1.8.0_202]
	at org.apache.dubbo.rpc.AsyncRpcResult.whenCompleteWithContext(AsyncRpcResult.java:153) ~[dubbo-2.7.3.jar:2.7.3]
	at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$CallbackRegistrationInvoker.invoke(ProtocolFilterWrapper.java:159) ~[dubbo-2.7.3.jar:2.7.3]
	at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:152) ~[dubbo-2.7.3.jar:2.7.3]
	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:102) ~[dubbo-2.7.3.jar:2.7.3]
	at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:193) ~[dubbo-2.7.3.jar:2.7.3]
	at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:51) ~[dubbo-2.7.3.jar:2.7.3]
	at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57) ~[dubbo-2.7.3.jar:2.7.3]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_202]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_202]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_202]

原因分析:

一、查看服务端控制台输出错误日志如下:

ERROR 8216 — [20001-thread-16] .d.r.f.ExceptionFilter$ExceptionListener : [DUBBO] Got unchecked and undeclared exception which called by 192.168.*.*. service: com.xiaozhou.dynamic.api.ArticleApi, method: queryArticleDtoByAuth, exception: com.xiaozhou.common.domain.BusinessException: 对不起,您没有权限访问, dubbo version: 2.7.3, current host: 192.168.*.*

二、查阅相关内容与源码分析

现象是dubbo的ExceptionFilter类将自定义异常封装成RuntimeException后抛出,上面消费端打印异常也可看出;然后下面为org.apache.dubbo.rpc.filter.ExceptionFilter中的onResponse源码分析结论。

1.异常类不是RuntimeException并且是Exception时,直接抛出

2.异常类是在方法签名上声明的抛出异常时,return 直接抛出

3.异常类和接口类在同一个jar包中时,直接抛出

4.异常类是如为"java."或"javax."开头的类名时(JDK的),直接抛出

5.异常类是dubbo自己的异常RpcException类时,直接抛出

6.其他,封装成RuntimeException类抛出


解决方案:

根据以上的原因可以对应方案:

1.自定义异常类改成Exception继承类,启动checked不通过,不太现实

2.在对应的服务接口方法上直接throw抛出自定义异常

3.将自定义异常与接口类放置同一个jar包中

4.重写dubbo的org.apache.dubbo.rpc.filter.ExceptionFilter,在dubbo服务端中如下操作:

  • 将ExceptionFilter类源码copy出来,自定义类

  • 在项目中资源resources目录下新建META-INF目录,再新建的目录中再新建dubbo目录,然后在此dubbo目录中新建个com.alibaba.dubbo.rpc.Filter的文件,文件中增加一行自定义类路径,如下:

  • 在springboot的配置文件中新加dubbo.provider.filter配置,配置为:customExceptionFilter,-exception

  • 最后就是进行自定义类改造了,如下:

(1)直接判断如果为自定义异常类,直接return抛出

(2)直接判断如果为自定义异常类的类路径,直接return抛出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值