Dubbo抛出自定义异常时报:Got unchecked and undeclared exception

转载: http://blog.csdn.net/xlee1905/article/details/44660449

dubbo的service端定义有自定义异常进行throw的时候,却发现在Controller中无法instanceof,自己自定义的异常类被转换成了Runtime异常,dubbo源码:

[java]  view plain copy

  1. public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {  
  2.     try {  
  3.         Result result = invoker.invoke(invocation);  
  4.         if (result.hasException() && GenericService.class != invoker.getInterface()) {  
  5.             try {  
  6.                 Throwable exception = result.getException();  
  7.   
  8.                 // 如果是checked异常,直接抛出  
  9.                 if (! (exception instanceof RuntimeException) && (exception instanceof Exception)) {  
  10.                     return result;  
  11.                 }  
  12.                 // 在方法签名上有声明,直接抛出  
  13.                 try {  
  14.                     Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes());  
  15.                     Class<?>[] exceptionClassses = method.getExceptionTypes();  
  16.                     for (Class<?> exceptionClass : exceptionClassses) {  
  17.                         if (exception.getClass().equals(exceptionClass)) {  
  18.                             return result;  
  19.                         }  
  20.                     }  
  21.                 } catch (NoSuchMethodException e) {  
  22.                     return result;  
  23.                 }  
  24.   
  25.                 // 未在方法签名上定义的异常,在服务器端打印ERROR日志  
  26.                 logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()  
  27.                         + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()  
  28.                         + ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), exception);  
  29.   
  30.                 // 异常类和接口类在同一jar包里,直接抛出  
  31.                 String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());  
  32.                 String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());  
  33.                 if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)){  
  34.                     return result;  
  35.                 }  
  36.                 // 是JDK自带的异常,直接抛出  
  37.                 String className = exception.getClass().getName();  
  38.                 if (className.startsWith("java.") || className.startsWith("javax.")) {  
  39.                     return result;  
  40.                 }  
  41.                 // 是Dubbo本身的异常,直接抛出  
  42.                 if (exception instanceof RpcException) {  
  43.                     return result;  
  44.                 }  
  45.   
  46.                 // 否则,包装成RuntimeException抛给客户端  
  47.                 return new RpcResult(new RuntimeException(StringUtils.toString(exception)));  
  48.             } catch (Throwable e) {  
  49.                 logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost()  
  50.                         + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()  
  51.                         + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);  
  52.                 return result;  
  53.             }  
  54.         }  
  55.         return result;  
  56.     } catch (RuntimeException e) {  
  57.         logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()  
  58.                 + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()  
  59.                 + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);  
  60.         throw e;  
  61.     }  
  62. }  

        所以在dubbo的service端想抛出自定义异常,只能通过在service端的接口方法上声明所要抛出的异常,或者将异常类与接口同包,再或者是接口的实现类再实现dubbo的GenericService接口。

        对于第一种方案没有使用,因为它对代码的入侵比较严重。

        第二种方案可以实现,可对于目前的业务框架,让接口类和异常类同包则变得不太可能。

        所以最后选择了让接口实现类再实现GenericService接口,而对于其需要实现的$invoke方法则没有做任何的方法体处理,直接废弃。

        对于dubbo的service端自定义异常类的处理,有些不理解的就是,为什么dubbo需要对自定义异常类做一次Runtime异常的转化,而不是直接抛出原异常类型。或者有没有对dubbo更了解的朋友,有对自定义异常更好的处理方法。

参考

Dubbo生产者抛出自定义异常的问题_代码菜鸟旺仔-CSDN博客_dubbo 自定义异常

猜你喜欢

转载自blog.csdn.net/gaoshan12345678910/article/details/120956394