onErrorResume无法按预期工作

时间:2017-05-30 22:51:32

标签: java spring project-reactor spring-webflux

我正在尝试使用WebFlux而且我看到的行为我不太明白,我怀疑这是WebFlux或可能是Reactor的错误,但我需要确认。

我试图创建一个可重复性最小的案例,其中包含一个非常简单的HandlerFunction,它尝试返回200响应,但在创建正文时抛出异常,然后尝试使用onErrorResume来代替返回404响应。

处理程序如下所示:

public Mono<ServerResponse> reproduce(ServerRequest request){
        return ServerResponse.ok()
        .contentType(APPLICATION_JSON)
        .body(Mono.fromCallable(this::trigger),String.class)
        .onErrorResume(MinimalExampleException.class,e->ServerResponse.notFound().build());
}

我希望在调用关联的端点时我会收到404响应。相反,我所看到的是一个带有日志消息的500响应,表明Spring认为在请求处理过程中存在未处理的异常。

当我在onErrorResume内部断点时,我看到两个处理程序正在注册,我在上面的方法中注册了一个处理程序,以及一个由Spring注册的处理程序(在RouterFunctions.toHttpHandler内部),用于{{1}的实例}。然后在处理请求期间,我只看到第二个处理程序(由Spring注册的处理程序)被调用,而不是在抛出的异常上匹配,然后进入根级处理程序。

我可以说,Spring在路由器级覆盖了ErrorResume,阻止了我在Handler中注册的那个被调用。这是预期的行为吗?有没有更好的方法来完成我正在尝试的事情?

1 个答案:

答案 0 :(得分:5)

框架确实有一个“catch-all”,在调用.body(...)后面的任何内容之前调用它。这是设计的,我认为很难避免。

我看到3个解决方案:

  1. 转动操作链
  2. 像这样:

    return Mono.fromCallable(this::trigger)
               .flatMap(s -> ServerResponse.ok()
                            .contentType(MediaType.TEXT_PLAIN)
                            .syncBody(s))
               .onErrorResume(MinimalExampleException.class,
                            e -> ServerResponse.notFound().build());
    
    1. 使用ResponseStatusException
    2. 您可以将onErrorResume置于与fromCallable()相同的级别(在正文调用内),通过错误单声道将特定错误转换为ResponseStatusException

      Mono.fromCallable(this::trigger)
          .onErrorResume(MinimalExampleException.class,
              e->Mono.error(new ResponseStatusException(404, "reason message", e)))
      
      1. 使用例外处理程序
      2. 您应该能够使用@ExceptionHandler注释方法来处理您的特定异常。

相关问题