为什么要写这篇文章呢?因为公司在使用Dubbo时并没有对Dubbo的用法做深入的了解,而是属于拿来就用,随着自己的想法来使用。这样很不好,就像天龙八部的鸠摩智练习错误的六脉神剑一样,方式不对,就容易走火入魔。下面是我近来在空闲时间对Dubbo的一些学习,也纠正了之前的一些错误用法,在此做一下记录:
接口定义及异常处理
原来错误的做法
先说说最初使用时的做法:
由于Provider和Consumer实际上就是一个服务端和一个客户端的关系。在实际应用当中,和APP直接交互的tomcat服务器就是客户端。那么在我们最初对Dubbo不了解的情况下,就照着APP接口的设计依样画葫芦,定义了一个ResponseDTO
:
public class ResponseDTO<T> implements Serializable {
private static final long serialVersionUID = 4082846602141879024L;
private boolean status = true;
private String msg;
private Exception exception;
private T data;
}
然后在Dubbo中提供接口时,会使用try...catch
的方式,将异常信息塞到ResponseDTO
中去。这样一来有几点坏处:
- 增加了代码的重复度和复杂度
- 可能会造成某些
Exception
在客户端无法被反序列化
- 无法通过Dubbo提供的拦截器来处理异常
那么,其实我们应该怎么做呢?
直接就像定义普通方法那样定义接口就好了,无需关心异常情况。因为Dubbo已经默认提供了ExceptionFilter
来帮助我们处理异常,这个Filter具体是用来干什么的呢?下面贴出核心代码,非常容易理解:
Throwable exception = result.getException();
if (!(exception instanceof RuntimeException)
&& (exception instanceof Exception)) {
return result;
}
try {
Method method = invoker.getInterface().getMethod(
invocation.getMethodName(), invocation.getParameterTypes());
Class<?>[] exceptionClassses = method.getExceptionTypes();
for (Class<?> exceptionClass : exceptionClassses) {
if (exception.getClass().equals(exceptionClass)) {
return result;
}
}
} catch (NoSuchMethodException e) {
return result;
}
logger.error(
"Got unchecked and undeclared exception which called by "
+ RpcContext.getContext().getRemoteHost()
+ ". service: " + invoker.getInterface().getName()
+ ", method: " + invocation.getMethodName()
+ ", exception: " + exception.getClass().getName()
+ ": " + exception.getMessage(), exception);
String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());
String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());
if (serviceFile == null || exceptionFile == null
|| serviceFile.equals(exceptionFile)) {
return result;
}
String className = exception.getClass().getName();
if (className.startsWith("java.") || className.startsWith("javax.")) {
return result;
}
if (exception instanceof RpcException) {
return result;
}
return new RpcResult(new RuntimeException(
StringUtils.toString(exception)));
还记得刚才我们提出自己定义ResponseDTO
的三个弊端吗?这里我们再列一下:
- 增加了代码的重复度和复杂度
- 可能会造成某些
Exception
在客户端无法被反序列化
- 无法通过Dubbo提供的拦截器来处理异常
那么再看看Dubbo是如何通过ExceptionFilter
来解决的:
- 在Dubbo中提供接口时,我们无需每个方法都用
try...catch
包裹,然后组装ResponseDTO
对象。而在客户端,也可以直接像调用本地方法一样调用Dubbo
的方法,无需再处理ResponseDTO
对象
- 仔细看上面的核心代码,在解决的一个最核心的问题就是担心客户端无法反序列化,所以也就有了最后一行,将无法反序列化的
Exception
包装成RuntimeException
- 我们可以通过自己写Filter来处理异常。最典型的,可能有的公司要求监控error日志,那么并不需要打error日志的异常我们可以通过重写Filter来实现。
所以对于接口定义和异常处理来说,正确的打开方式就是:
- 像定义普通方法一样定义接口,客户端直接调用即可
- 利用好Filter来处理异常信息
<script type="text/javascript">
$(function () {
$('pre.prettyprint code').each(function () {
var lines = $(this).text().split('\n').length;
var $numbering = $('<ul/>').addClass('pre-numbering').hide();
$(this).addClass('has-numbering').parent().append($numbering);
for (i = 1; i <= lines; i++) {
$numbering.append($('<li/>').text(i));
};
$numbering.fadeIn(1700);
});
});
</script>
分享到:
相关推荐
### Dubbo开发原理及相关技术学习文档 #### 1. Dubbo是什么?Dubbo需要用到哪些软件? **Dubbo** 是一款高性能、轻量级的开源Java RPC框架,它提供了面向接口的远程方法调用机制,使得应用程序可以像调用本地方法...
在使用Eclipse这样的IDE打开项目时,开发者可以查看源代码,理解RPC调用的实现细节,包括服务的创建、发布、客户端的调用以及异常处理等。同时,开发者还可以运行测试用例,实际体验RPC调用的过程。 总的来说,这个...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...