有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何将选中的异常从CompletableFuture传递给ControllerAdvice

如何使controllerAdvice类捕获从completablefutrue引发的异常。 在下面的代码中,我有一个方法checkId,它抛出一个选中的异常。我使用completablefuture调用此方法,并将选中的异常包装在CompletionException中。虽然我在控制器建议类中有一个处理程序方法,但它没有处理错误

package com.example.demo.controller;
@RestController
public class HomeController {

    @GetMapping(path = "/check")
    public CompletableFuture<String> check(@RequestParam("id") int id) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return checkId(id);
            }
            catch (Exception e) {
                throw new CompletionException(e);
            }
        });
    }

    public String checkId(int id) throws Exception  {
        if (id < 0) {
            throw new MyException("Id must be greater than 0");
        }
        return "id is good";
    }

}

-

package com.example.demo;
public class MyException extends Exception {

    public MyException(String message) {
        super(message);
    }

}

-

package com.example.demo;
@ControllerAdvice
public class ExceptionResolver {

    @ExceptionHandler(value = CompletionException.class)
    public String handleCompletionException(CompletionException ex) {
        return ex.getMessage();
    }

}

--

package com.example.demo;
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

堆栈跟踪:

com.example.demo.MyException: Id must be greater than 0
    at com.example.demo.controller.HomeController.checkId(HomeController.java:30) ~[classes/:na]
    at com.example.demo.controller.HomeController.lambda$0(HomeController.java:19) ~[classes/:na]
    at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700) ~[na:na]
    at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1692) ~[na:na]
    at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) ~[na:na]
    at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020) ~[na:na]
    at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656) ~[na:na]
    at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594) ~[na:na]
    at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177) ~[na:na]

2020-01-24 14:38:30.489 ERROR 938 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.example.demo.MyException: Id must be greater than 0] with root cause

com.example.demo.MyException: Id must be greater than 0
    at com.example.demo.controller.HomeController.checkId(HomeController.java:30) ~[classes/:na]
    at com.example.demo.controller.HomeController.lambda$0(HomeController.java:19) ~[classes/:na]
    at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700) ~[na:na]
    at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1692) ~[na:na]
    at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) ~[na:na]
    at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020) ~[na:na]
    at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656) ~[na:na]
    at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594) ~[na:na]
    at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177) ~[na:na]

共 (1) 个答案

  1. # 1 楼答案

    @Deadpool和我能够识别问题

    在completableFuture代码的catch块中,异常被包装在运行时异常CompletionException异常中。当端点被命中时,在某个点上CompletionException异常被解包为MyException类型的原始异常(选中的异常)。这意味着处理程序方法应该处理类型为MyException的异常,而不是CompletionException

    @ExceptionHandler(value = MyException.class)
    @ResponseBody 
    public String handleCompletionException(MyException ex) { 
         return ex.getMessage(); 
    }