dubbo版本2.7.4-release
1.測試代碼
1.1 聲明接口
public interface DemoService {
int testException();
}
1.2 接口實現
public class DemoServiceImpl implements DemoService {
private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
@Override
public int testException() {
int a = 1/0;
return a;
}
}
1.3 provider啓動類
public class Application {
public static void main(String[] args) throws Exception {
ServiceConfig<DemoServiceImpl> service = new ServiceConfig<>();
service.setApplication(new ApplicationConfig("dubbo-demo-api-provider"));
service.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
service.setInterface(DemoService.class);
service.setRef(new DemoServiceImpl());
service.export();
System.in.read();
}
}
1.3 consumer測試類
public class Application {
public static void main(String[] args) throws IOException {
ReferenceConfig<DemoService> reference = new ReferenceConfig<>();
reference.setApplication(new ApplicationConfig("dubbo-demo-api-consumer"));
reference.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
reference.setInterface(DemoService.class);
reference.setTimeout(100000);
DemoService service = reference.get();
int i = service.testException();
System.out.println(message);
}
}
1.4 運行1.3結果
2 .反編譯代理類,查看異常捕獲方式;
org.apache.dubbo.common.bytecode.Wrapper1
package org.apache.dubbo.common.bytecode;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import org.apache.dubbo.common.bytecode.ClassGenerator;
import org.apache.dubbo.common.bytecode.NoSuchMethodException;
import org.apache.dubbo.common.bytecode.NoSuchPropertyException;
import org.apache.dubbo.common.bytecode.Wrapper;
import org.apache.dubbo.demo.provider.DemoServiceImpl;
public class Wrapper1
extends Wrapper
implements ClassGenerator.DC {
.....
public Object invokeMethod(Object object, String string, Class[] arrclass, Object[] arrobject) throws InvocationTargetException {
DemoServiceImpl demoServiceImpl;
try {
demoServiceImpl = (DemoServiceImpl)object;
}
catch (Throwable throwable) {
throw new IllegalArgumentException(throwable);
}
try {
if ("sayHello".equals(string) && arrclass.length == 1) {
return demoServiceImpl.sayHello((String)arrobject[0]);
}
if ("testException".equals(string) && arrclass.length == 0) {
return new Integer(demoServiceImpl.testException());
}
}
catch (Throwable throwable) {
//將java.lang.ArithmeticException異常封裝成InvocationTargetException繼續往上拋
throw new InvocationTargetException(throwable);
}
throw new NoSuchMethodException(new StringBuffer().append("Not found method \"").append(string).append("\" in class org.apache.dubbo.demo.provider.DemoServiceImpl.").toString());
}
}
3.provider返回包含異常結果
public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
Logger logger = LoggerFactory.getLogger(AbstractProxyInvoker.class);
......
@Override
public Result invoke(Invocation invocation) throws RpcException {
try {
Object value = doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
CompletableFuture<Object> future = wrapWithFuture(value, invocation);
AsyncRpcResult asyncRpcResult = new AsyncRpcResult(invocation);
future.whenComplete((obj, t) -> {
AppResponse result = new AppResponse();
if (t != null) {
if (t instanceof CompletionException) {
result.setException(t.getCause());
} else {
result.setException(t);
}
} else {
result.setValue(obj);
}
asyncRpcResult.complete(result);
});
return asyncRpcResult;
} catch (InvocationTargetException e) {
if (RpcContext.getContext().isAsyncStarted() && !RpcContext.getContext().stopAsync()) {
logger.error("Provider async started, but got an exception from the original method, cannot write the exception back to consumer because an async result may have returned the new thread.", e);
}
//異常封裝到DefaultAsyncResult,返回給consumer
return AsyncRpcResult.newDefaultAsyncResult(null, e.getTargetException(), invocation);
} catch (Throwable e) {
throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
}
4.consumer如何處理異常
org.apache.dubbo.rpc.AppResponse#recreate
public class AppResponse extends AbstractResult implements Serializable {
........
@Override
public Object recreate() throws Throwable {
if (exception != null) {
// fix issue#619
try {
// get Throwable class
Class clazz = exception.getClass();
while (!clazz.getName().equals(Throwable.class.getName())) {
clazz = clazz.getSuperclass();
}
// get stackTrace value
Field stackTraceField = clazz.getDeclaredField("stackTrace");
stackTraceField.setAccessible(true);
Object stackTrace = stackTraceField.get(exception);
if (stackTrace == null) {
exception.setStackTrace(new StackTraceElement[0]);
}
} catch (Exception e) {
// ignore
}
//這裏拋出服務端返回的異常
throw exception;
}
return result;
}
}
這裏麻煩點的就是如何反編譯代理類
可參考這個:
http://dubbo.apache.org/zh-cn/docs/source_code_guide/service-invoking-process.html
2.1節服務調試