美文网首页
dubbo 抛出自定义异常正常处理方法

dubbo 抛出自定义异常正常处理方法

作者: 6596dfcf0778 | 来源:发表于2019-02-22 14:00 被阅读0次

    dubbo provider抛出一个自定义异常,consuemer获取失败

    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();
    
                        // directly throw if it's checked exception
                        if (!(exception instanceof RuntimeException) && (exception instanceof Exception)) {
                            return result;
                        }
                        // directly throw if the exception appears in the signature
                        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;
                        }
    
                        // for the exception not found in method's signature, print ERROR message in server's log.
                        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);
    
                        // directly throw if exception class and interface class are in the same jar file.
                        String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());
                        String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());
                        if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)) {
                            return result;
                        }
                        // directly throw if it's JDK exception
                        String className = exception.getClass().getName();
                        if (className.startsWith("java.") || className.startsWith("javax.")) {
                            return result;
                        }
                        // directly throw if it's dubbo exception
                        if (exception instanceof RpcException) {
                            return result;
                        }
    
                        // otherwise, wrap with RuntimeException and throw back to the client
                        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;
            }
    

    从源码中可以看出,异常直接返回有以下几种情况

    1. 抛出的是一个Exception 而非 RuntimeException
    2. 在方法签名上有声明
    3. 异常类和接口声明在同一个包里
    4. 是JDK 自身异常
    5. 是dubbo 自身异常

    由以上几种情况可以看出可以有以下几种解决方案

    1. 在方法签名上throws 异常
    2. 将异常类和接口声明放在同一个类中(推荐,适用于新项目和小项目改造)
    3. 重写dubbo 的异常处理类ExceptionFilter(参考文章 https://www.jianshu.com/p/7e7076212bd0)

    相关文章

      网友评论

          本文标题:dubbo 抛出自定义异常正常处理方法

          本文链接:https://www.haomeiwen.com/subject/mnxeyqtx.html