Dubbo生产者抛出自定义异常的问题
2017-07-27 14:40
218 查看
在使用dubbo的过程中,在dubbo的service端定义有自定义异常进行throw的时候,却发现在customer的Controller中无法instanceof,自己自定义的异常类被转成了Runtime异常,有点不理解。在翻看dubbo源码的时候,发现确实如此:
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
try {
Result result = invoker.invoke(invocation);
if (result.hasException() && GenericService.class != invoker.getInterface()) {
try {
Throwable exception = result.getException();
// 如果是checked异常,直接抛出
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;
}
// 未在方法签名上定义的异常,在服务器端打印ERROR日志
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);
// 异常类和接口类在同一jar包里,直接抛出
String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());
String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());
if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)){
return result;
}
// 是JDK自带的异常,直接抛出
String className = exception.getClass().getName();
if (className.startsWith("java.") || className.startsWith("javax.")) {
return result;
}
// 是Dubbo本身的异常,直接抛出
if (exception instanceof RpcException) {
return result;
}
// 否则,包装成RuntimeException抛给客户端
return new RpcResult(new RuntimeException(StringUtils.toString(exception)));
} catch (Throwable e) {
logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost()
+ ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()
+ ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
return result;
}
}
return result;
} catch (RuntimeException e) {
logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()
+ ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()
+ ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
throw e;
}
}
// 否则,包装成RuntimeException抛给客户端
return new RpcResult(new RuntimeException(StringUtils.toString(exception)));
最后这一段是是把我们的自定义异常给重新封装了一下了,所以我们就捕获不到自定义异常了。
导致他走这一步的原因是因为:生产者把方法接口给消费者调用的时候,没有在接口类里面对该方法进行声明异常,
导致在上面的源码中的判断有问题。
method.getExceptionTypes() =[], 没有将异常return出来,走到最后被包装成RuntimeException抛给客户端。
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
try {
Result result = invoker.invoke(invocation);
if (result.hasException() && GenericService.class != invoker.getInterface()) {
try {
Throwable exception = result.getException();
// 如果是checked异常,直接抛出
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;
}
// 未在方法签名上定义的异常,在服务器端打印ERROR日志
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);
// 异常类和接口类在同一jar包里,直接抛出
String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());
String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());
if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)){
return result;
}
// 是JDK自带的异常,直接抛出
String className = exception.getClass().getName();
if (className.startsWith("java.") || className.startsWith("javax.")) {
return result;
}
// 是Dubbo本身的异常,直接抛出
if (exception instanceof RpcException) {
return result;
}
// 否则,包装成RuntimeException抛给客户端
return new RpcResult(new RuntimeException(StringUtils.toString(exception)));
} catch (Throwable e) {
logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost()
+ ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()
+ ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
return result;
}
}
return result;
} catch (RuntimeException e) {
logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()
+ ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()
+ ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
throw e;
}
}
// 否则,包装成RuntimeException抛给客户端
return new RpcResult(new RuntimeException(StringUtils.toString(exception)));
最后这一段是是把我们的自定义异常给重新封装了一下了,所以我们就捕获不到自定义异常了。
导致他走这一步的原因是因为:生产者把方法接口给消费者调用的时候,没有在接口类里面对该方法进行声明异常,
导致在上面的源码中的判断有问题。
method.getExceptionTypes() =[], 没有将异常return出来,走到最后被包装成RuntimeException抛给客户端。
相关文章推荐
- Dubbo生产者抛出自定义异常的问题
- Dubbo生产者抛出自定义异常的问题
- Dubbo抛出自定义异常时报:Got unchecked and undeclared exception
- dubbo处理自定义异常问题
- Dubbo抛出自定义异常
- Dubbo抛出自定义异常
- dubbo捕获提供者抛出的自定义异常
- 中C# catch 块中可以俘获 SQL Server 抛出的自定义异常(RAISERROR)
- 关于C++异常抛出指针问题的探讨
- 用自定义的异常类接管未知的异常类抛出
- OAF学习笔记-16-自定义异常的抛出
- Java中关于子类覆盖父类的抛出异常问题
- java基础16 捕获、抛出以、自定义异常和 finally 块(以及关键字:throw 、throws)
- SQL Server 抛出自定义异常,由C#程序俘获之并进行相应的处理
- 七天学会ASP.NET MVC (六)——线程问题、异常处理、自定义URL
- Java 如何抛出异常、自定义异常
- 浅析在C#里面抛出SAP里面自定义的异常信息
- C++ 让new操作符失败时抛出自定义的异常
- struts2抛出异常自定义跳转页面
- 抛出自定义异常,spring AOP事务不回滚的解决方案