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

dubbo服务提供端自定义异常,在消费端变成了RuntimeException,导致无法捕获自定义异常。

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;

}

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

抛出的是一个Exception 而非 RuntimeException

在方法签名上有声明

异常类和接口声明在同一个包里

是JDK 自身异常

是dubbo 自身异常

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

在方法签名上throws 自义定异常

将异常类和接口声明放在同一个类中(推荐,适用于新项目和小项目改造)

重写dubbo 的异常处理类ExceptionFilter

你可能感兴趣的:(dubbo全局异常处理)