我正在使用如下的completablefuture进行并行调用,
public Response getResponse() {
Response resultClass = new Response();
try {
CompletableFuture<Optional<ClassA>> classAFuture
= CompletableFuture.supplyAsync(() -> service.getClassA() );
CompletableFuture<ClassB> classBFuture
= CompletableFuture.supplyAsync(() -> {
try {
return service.getClassB();
}
catch (Exception e) {
throw new CompletionException(e);
}
});
CompletableFuture<Response> responseFuture =
CompletableFuture.allOf(classAFuture, classBFuture)
.thenApplyAsync(dummy -> {
if (classAFuture.join().isPresent() {
ClassA classA = classAFuture.join();
classA.setClassB(classBFuture.join());
response.setClassA(classA)
}
return response;
});
responseFuture.join();
} catch (CompletionExecution e) {
throw e;
}
return response;
}
我需要为return service.getClassB()
添加try-catch,因为它在方法getClassB
中抛出异常。
现在我面临的问题是,如果service.getClassB()
抛出错误,它总是被包裹在java.util.concurrent.ExecutionException
中。在这种情况下,该方法抛出UserNameNotFoundException,但它被封装在ExecutionException
中,并且没有在@ControllerAdvice
异常处理程序类的正确位置捕获。我尝试了不同的选择使用一次性,但没有帮助。
有没有一种好的方法来处理异常并打开包装并将其发送到@ControllerAdvice
类?
您的代码有几个错误,比如引用了一个未在此代码中声明的变量response
,很可能是开头声明的resultClass
。ClassA classA = classAFuture.join();
行突然忽略了这个future封装了一个Optional
,并且缺少)
和;
分隔符。
此外,当有一个干净的替代方案时,应该避免从周围的代码中访问变量。此外,使用allOf
组合两个期货是不必要的复杂操作。
如果我正确理解你的意图,你想做一些类似的事情
public Response getResponse() {
return CompletableFuture.supplyAsync(() -> service.getClassA())
.thenCombine(CompletableFuture.supplyAsync(() -> {
try {
return service.getClassB();
}
catch(ExecutionException e) {
throw new CompletionException(e.getCause());
}
}), (optA, b) -> {
Response response = new Response();
optA.ifPresent(a -> {
a.setClassB(b);
response.setClassA(a);
});
return response;
})
.join();
}
解决所描述问题的关键点是捕获最特定的异常类型。当您捕获ExecutionException
时,您知道它将包装实际的异常,并且可以无条件地提取它。当getClassB()
声明您必须捕获的其他已检查异常时,添加另一个catch
子句,但要特定,而不是捕获Exception
,例如
try {
return service.getClassB();
}
catch(ExecutionException e) {
throw new CompletionException(e.getCause());
}
catch(IOException | SQLException e) { // all of getClassB()’s declared exceptions
throw new CompletionException(e); // except ExecutionException, of course
}