我正在尝试使用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中注册的那个被调用。这是预期的行为吗?有没有更好的方法来完成我正在尝试的事情?
答案 0 :(得分:5)
框架确实有一个“catch-all”,在调用.body(...)
后面的任何内容之前调用它。这是设计的,我认为很难避免。
我看到3个解决方案:
像这样:
return Mono.fromCallable(this::trigger)
.flatMap(s -> ServerResponse.ok()
.contentType(MediaType.TEXT_PLAIN)
.syncBody(s))
.onErrorResume(MinimalExampleException.class,
e -> ServerResponse.notFound().build());
ResponseStatusException
您可以将onErrorResume
置于与fromCallable()
相同的级别(在正文调用内),通过错误单声道将特定错误转换为ResponseStatusException:
Mono.fromCallable(this::trigger)
.onErrorResume(MinimalExampleException.class,
e->Mono.error(new ResponseStatusException(404, "reason message", e)))
您应该能够使用@ExceptionHandler
注释方法来处理您的特定异常。