Java 当未接收返回值的@Async方法引发异常时,将无法捕获出现的异常信息

Java 当未接收返回值的@Async方法引发异常时,将无法捕获出现的异常信息,java,spring,asynchronous,Java,Spring,Asynchronous,我使用AsyncConfigurer实现异步配置 代码显示如下: @Slf4j @Configuration @EnableAsync public class AsyncConfiguration implements AsyncConfigurer { @Bean @Override public Executor getAsyncExecutor() { log.warn("-----------------start asyncServi

我使用AsyncConfigurer实现异步配置

代码显示如下:

@Slf4j
@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {
    @Bean
    @Override
    public Executor getAsyncExecutor() {
        log.warn("-----------------start asyncServiceExecutor----------------");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(8);
        executor.setMaxPoolSize(16);
        executor.setQueueCapacity(64);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setThreadNamePrefix("SpringAsyncThread-");
        executor.initialize();
//        return executor;
        return new HandlingExecutor(executor);
    }
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SpringAsyncExceptionHandler();
    }

    class SpringAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
            throwable.printStackTrace();
            log.error("Exception occurs in async method", throwable.getMessage());
        }
    }
}
在这一点上,我有一个异步方法

schedulingService.acceptTask(任务);这是一个返回值为ListenableFuture并由@Async标记的方法

@PostMapping("processing")
    public RestResult<Boolean> acceptTask(@RequestBody Task task) {
        log.error(
                "HPC服务接到任务处理-task的linkId:{},rootId{}",
                task.getPipeLinkId().toHexString(),
                task.getRootId().toHexString());
        schedulingService.acceptTask(task);
        return RestResult.success(true);
    }

    @PostMapping("wait/processing")
    public RestResult<Boolean> acceptTaskWait(@RequestBody Task task) {
        log.error(
                "HPC服务接到任务处理-task的linkId:{},rootId{}",
                task.getPipeLinkId().toHexString(),
                task.getRootId().toHexString());
        try {
            return RestResult.success(schedulingService.acceptTask(task).get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            return RestResult.success(true);
        }
    }
但它尚未实施。我认为这是一个非常严重的问题。如果有一个好办法,请告诉我如何解决它和这个问题的原因。非常感谢。我使用的springboot版本是2.2.7,因为您已经有了一个新的版本,然后使用它,另一件需要了解的事情是,还支持从控制器方法返回一个
未来的
,框架将正确地处理它

在这种情况下,您可能希望将
ListenableFuture
转换为
CompletableFuture
,并调用
然后应用
方法来转换结果

@PostMapping(“等待/处理”)
公共未来acceptTaskWait(@RequestBody任务){
日志错误(
“HPC服务接到任务处理-任务的linkId:{},rootId{}“,
task.getPipeLinkId().toHexString(),
task.getRootId().toHexString());
ListenableFuture结果=schedulingService.acceptTask(任务);
返回result.completable().thenApply(RestResult::success);
}
由于您已经有了一个,然后使用它,另一件需要意识到的事情是,从控制器方法返回一个
未来的
也是受支持的,并且框架将正确地处理它

在这种情况下,您可能希望将
ListenableFuture
转换为
CompletableFuture
,并调用
然后应用
方法来转换结果

@PostMapping(“等待/处理”)
公共未来acceptTaskWait(@RequestBody任务){
日志错误(
“HPC服务接到任务处理-任务的linkId:{},rootId{}“,
task.getPipeLinkId().toHexString(),
task.getRootId().toHexString());
ListenableFuture结果=schedulingService.acceptTask(任务);
返回result.completable().thenApply(RestResult::success);
}

async没有在这里添加任何内容。您直接对结果调用
get()。所以你基本上增加了很多复杂性,但没有得到任何东西。当然,我知道异步get会使它阻塞,失去异步的意义。我的问题是,我需要这个方法是一个带有返回值的异步方法,如果我不接受这个返回值,这个异步方法的异常也可以被捕获并打印出来。同时,我必须调用此方法来执行同步响应。当然,这次我肯定会打印异常,但问题是我想要捕获的是有一个返回值,但它尚未被处理。返回值时发生异常只返回
未来
,或者如果要执行其他操作,请添加2个回调。1表示正常,1表示不正常。查看或使其成为一个可完成的未来,执行您想要的操作并从方法返回。异步在这里不添加任何内容。您直接对结果调用
get()。所以你基本上增加了很多复杂性,但没有得到任何东西。当然,我知道异步get会使它阻塞,失去异步的意义。我的问题是,我需要这个方法是一个带有返回值的异步方法,如果我不接受这个返回值,这个异步方法的异常也可以被捕获并打印出来。同时,我必须调用此方法来执行同步响应。当然,这次我肯定会打印异常,但问题是我想要捕获的是有一个返回值,但它尚未被处理。返回值时发生异常只返回
未来
,或者如果要执行其他操作,请添加2个回调。1表示正常,1表示不正常。看到或使其成为一个可完成的未来,做你想做的并从方法中返回。返回未来的控制器不满足我。通过你的第一个回答,我仍然能听到你的未来。addCallback编写了其处理方法,并在出现异常时成功打印出日志,即使我没有接收或处理它,也可以正确打印此异步方法的返回值,但这似乎与@Async和Spring无关。返回Future的控制器不能满足我的要求。通过你的第一个回答,我仍然能听到你的未来。addCallback编写了其处理方法,并在出现异常时成功打印出日志,即使我没有接收或处理它,也可以正确打印此异步方法的返回值,但这似乎与@Async和Spring无关
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        System.out.println("进入异常处理");
        return new SpringAsyncExceptionHandler();
    }