【问题标题】:Spring Webflux - Proper way to throw checked custom exception (not RuntimeException)Spring Webflux - 抛出检查的自定义异常(不是 RuntimeException)的正确方法
【发布时间】:2020-08-24 23:24:25
【问题描述】:

请问在 Spring webflux 中抛出已检查的自定义异常的正确方法是什么? 我要坚持,它是关于已检查的自定义异常,比如 MyException.java,而不是 RuntimeException,它是关于 抛出异常,而不是处理异常。

我尝试了以下方法:

@Controller
@SpringBootApplication
public class QuestionHowToThrowException {

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

    @PostMapping(path = "/question", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Mono<ResponseEntity<QuestionResponse>> question(@RequestBody QuestionRequest questionRequest) {
        Mono<FirstStep> firstStepMono = WebClient.create().post().uri("http://firstWebService:8111/getFirstStep")
                .body(questionRequest.getThing(), String.class).retrieve().bodyToMono(FirstStep.class);
        Mono<SecondStep> secondStepMono = firstStepMono.map(oneFirstStep -> getSecondStepFromFirstStepAfterCheck(oneFirstStep));
        return secondStepMono.map(oneSecondStep -> ResponseEntity.ok(new QuestionResponse(oneSecondStep.getSecondThing())));
    }

    private SecondStep getSecondStepFromFirstStepAfterCheck(FirstStep firstStep) throws MyException {
        if (firstStep.getThingNeedsToCheckCanThrowException().equals("exception")) {
            throw new MyException("exception");
        } else {
            return new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good");
        }
    }

    public class QuestionRequest {
        private String thing;
        public String getThing() {
            return thing;
        }
    }

    public class QuestionResponse {
        private String response;
        public QuestionResponse(String response) {
            this.response = response;
        }
    }

    public class FirstStep {
        private String thingNeedsToCheckCanThrowException;
        public String getThingNeedsToCheckCanThrowException() {
            return thingNeedsToCheckCanThrowException;
        }
    }

    public class SecondStep {
        private String secondThing;
        public SecondStep(String secondThing) {
            this.secondThing = secondThing;
        }
        public String getSecondThing() {
            return secondThing;
        }
    }

}

这是不可能的,因为 getSecondStepFromFirstStepAfterCheck 方法中存在未处理的异常。

如果我抛出并传播,private SecondStep getSecondStepFromFirstStepAfterCheck(FirstStep firstStep) 抛出 MyException lambda 调用者方法不高兴。

请问在 webflux 中抛出自定义异常的最干净和正确的方法是什么?

谢谢

【问题讨论】:

    标签: java spring-boot exception spring-webflux


    【解决方案1】:

    通读您的示例代码,您似乎正试图在您的Mono 上引入一些错误处理。

    您可以通过扩展RuntimeException 类来创建未经检查的异常。如果你想要一个强制处理的检查异常,你可以简单地扩展Exception

    public class MyException extends RuntimeException {
        public MyException(String msg) {
           super(s);
        }
    }
    

    在 Reactor 项目中抛出异常的最干净的方法实际上就是抛出它。有一些错误处理函数允许您为某些错误情况提供不同的流程。

    好消息是您有几个选项可以为错误处理提供一些流控制。

    Project Reactor 在Mono 对象上提供了其中几个方法。

    doOnError(),onErrorContinue(),onErrorReturn(),onErrorStop(),onErrorMap()

    我不完全确定您想通过以下示例代码实现什么目标。

     return Mono.error(new MyException("exception"));
            } else {
     return Mono.just(new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good"));
    

    但这对于 onErrorMap() 来说似乎是一个很好的案例,因为您似乎正在尝试在这里翻译一些异常

    return Mono.just(new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good")
       .onErrorMap(e -> "translated result");
    

    【讨论】:

    • 你好@shinjw,谢谢你的建议。我遵循了你的想法,但我仍然被阻止。我现在做“用 Reactor 项目抛出异常的最干净的方法就是抛出它”请查看更新的签名 private SecondStep getSecondStepFromFirstStepAfterCheck(FirstStep firstStep) throws MyException { 但是,这不是编译,因为调用者现在有一个未处理的异常。你能提供一个sn-p吗?
    • MyException 是异常还是 RuntimeException?如果它是选中的Exception,那么您将不得不将您的异常重新抛出为 RuntimeException 以将其冒泡到您的 Mono 流中。
    • catch(Exception e) { throw new RuntimeException(e) }
    • 你是对的,这是一个例外。 public class MyException extends Exception { 我不想在这里开始另一个关于已检查与未检查异常的话题,但我想避免抛出运行时异常。请问有没有可能在不经历这种“重新投掷”的情况下达到同样的效果?
    【解决方案2】:

    对于我们的应用程序,我们有从 RuntimeException 扩展而来的自定义基础异常。然后我们有标准的异常处理,在将结果返回给最终用户之前寻找我们的自定义异常进行特殊处理。这允许我们使用正常的抛出机制,因为我们希望抛出的所有异常都会影响调用的顶层。

    对于性能问题,webflux 和响应式在每次调用的基础上的性能略低,尤其是对于不需要进行任何并行化的调用。然而,一旦将负载放到系统上,它往往会变得更加高性能,主要与垃圾收集有关。 map 和 flatMap 之间差异的开销充其量应该可以忽略不计。

    【讨论】:

      猜你喜欢
      • 2021-03-11
      • 2019-09-19
      • 1970-01-01
      • 1970-01-01
      • 2012-05-13
      • 2019-05-04
      • 2015-04-29
      • 2016-04-03
      • 2021-11-09
      相关资源
      最近更新 更多