【问题标题】:Exception Handling in Spring webfluxSpring webflux中的异常处理
【发布时间】:2021-11-12 19:07:48
【问题描述】:

我正在开发一个使用反应流的 Spring webflux 项目。我有一个如下用例,想知道如何以被动方式完成。

  @RestController
  public class Example {

    @GetMapping("/greet")
    public Mono<String> Test() {
       return Mono.just("Tim")
               .map(s -> s.toUpperCase())
               .map(s -> s.toLowerCase())
               .doOnSuccess(s -> validate(s)) // usecase is to validate here in middle of the pipeline
               .onErrorResume(ex -> Mono.just("Guest"))
               .map(s -> "Hi, "+s);
    }
   
  public void validate(String s) {
    if(s.length() < 5) {throw new RuntimeException("Name is short");}
  }
 
}

我知道这是一个人为的例子,但我有类似的东西。我认为在命中端点时抛出错误会导致浏览器屏幕上出现异常。但令我惊讶的是,它去了onErrorResume(),我得到了Hi, Guest作为回复。我想当throw用于在组装反应管道之前抛出异常时,它不会使用onErrorResume()。我在这里错过了什么?

同样提出问题 #2,如果我使用 Mono.error(new RuntimeException("Name is short")) 而不是 throw new RuntimeException("Name is short"),我该如何实现?有人可以回答我的2个问题。感谢您提出改进代码的建议。

【问题讨论】:

  • 请提供错误堆栈跟踪并尝试在元交换中发布您的建议问题
  • 附带说明,在编写函数式代码时,您应该避免使用 void 函数。您上面的功能有 2 个结果,无效或异常。这在功能世界中并不好。更合适的是public boolean hasLength(String s, int length) end 然后有一个 if statemtnt 如果它没有所需的长度会抛出异常

标签: java spring spring-boot reactive-programming spring-webflux


【解决方案1】:

我想当 throw 用于在响应式之前抛出异常 管道已组装,它不会使用 onErrorResume()

Mono::doOnSuccessMono 成功完成(管道已组装)时在执行时间触发。

请注意,在 doOnNextmap 等中间运算符中,您可以随意抛出异常,因为 Reactor 可以将它们转换为适当的错误信号,因为此时 Mono 已经在进行中。

如果我使用 Mono.error(new RuntimeException("Name is short")) 而不是 throw new RuntimeException("名字很短")?

您可以将doOnSuccessmap 替换为handle 运算符:

 return Mono.just("Tim")
            .handle((name, sink) -> {
                if(name.length() < 5){
                    sink.error(new RuntimeException("Name is short"));
                } else {
                    sink.next(name.toLowerCase());
                }
            })

【讨论】:

    【解决方案2】:

    对于第一个问题,您可以在onErrorResume 中添加谓词

    .onErrorResume(e -> !(e instanceof RuntimeException), ex -> Mono.just("Guest"))
    

    这样您就可以过滤可以返回预定义结果的错误。

    对于问题 #2,您可以将作为消费者的 doOnSuccess 替换为 flatMap 并返回 Mono forvalidate 方法:

        public Mono<String> Test() {
            return Mono.just("Tim")
                    .map(s -> s.toUpperCase())
                    .map(s -> s.toLowerCase())
                    .flatMap(s -> validate(s))
                    .onErrorResume(e -> !(e instanceof RuntimeException), ex -> Mono.just("Guest"))
                    .map(s -> "Hi, " + s);
        }
    
        public Mono<String> validate(String s) {
            return (s.length() < 5) ?
                    Mono.error(() -> new RuntimeException("Name is short")) :
                    Mono.just(s);
        }
    

    【讨论】:

      猜你喜欢
      • 2019-03-11
      • 2018-06-06
      • 2020-03-23
      • 1970-01-01
      • 1970-01-01
      • 2020-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多