项目中 CompletableFuture 的统一异常处理

发布于:2025-03-18 ⋅ 阅读:(16) ⋅ 点赞:(0)

项目中需要调用多个服务,如果使用 open-Feign 串行化调用,响应时间可能会比较长,后续使用了 CompletableFuture 和线程池进行异步调用,但是在调用时,可能存在调用的服务报错,导致整个查询方法直接抛出异常,无法继续后面的操作,注意其他异步调用的任务仍会处理完成。现在我想捕获调用时的异常,且不影响后续的执行。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RpcResult {
    private boolean isSuccess;
    private String message;
    private Object data;
}
@Slf4j
public class AsyncUtil {
    /**
     * 零元依赖 封装异步调用
     * 处理异常信息
     */
    public static CompletableFuture<RpcResult> asyncCall(
        Supplier<Object> task,
        String serviceName,
        ThreadPoolExecutor threadPoolExecutor
    ) {
        return CompletableFuture.supplyAsync(()->{
            try {
                Object data = task.get();
                String message = String.format("%s服务调用成功",serviceName);
                return new RpcResult(true, message, data);
            }catch (Throwable ex) {
                String errorMessage = String.format("%s服务调用失败", serviceName);
                log.error(errorMessage, ex);
                return new RpcResult(false, errorMessage, null);
            }
        });
    }
}

@Test
    public void testAsyncUtil(){
        PersonRpc personRpc = new PersonRpc();

        CompletableFuture<RpcResult> ageF = AsyncUtil.asyncCall(() -> {
            Integer age = 21;
            int i = 1 / 0;
            return age;
        }, "ageService", threadPoolExecutor);

        CompletableFuture<RpcResult> nameF = AsyncUtil.asyncCall(() -> {
            String name = "zhangsan";
            int i = 1 / 0;
            return name;
        }, "nameService", threadPoolExecutor);

        CompletableFuture<RpcResult> birthdayF = AsyncUtil.asyncCall(() -> {
            LocalDate birthday = LocalDate.parse("2003-10-29");
            return birthday;
        }, "birthdayService", threadPoolExecutor);

        CompletableFuture<Void> allFutures = CompletableFuture.allOf(ageF, nameF, birthdayF);
        CompletableFuture<PersonRpc> resultFuture = allFutures.thenApply(v -> {
            personRpc.setAge(ageF.join());
            personRpc.setName(nameF.join());
            personRpc.setBirthday(birthdayF.join());
            return personRpc;
        });

        System.out.println(resultFuture.join());
        System.out.println("执行结束");
    }

在这里插入图片描述
抽象了工具类 AsyncUtil 集中处理调用信息和异常信息,可以看到即使调用服务发生了异常,也能继续执行,发生异常后记录了报错信息且返回给前端状态信息。

正常情况下执行也没有问题
在这里插入图片描述