Java Spring5中的HTTP响应异常处理

Java Spring5中的HTTP响应异常处理,java,spring-boot,exception,spring-webflux,Java,Spring Boot,Exception,Spring Webflux,我正在开发一些使用SpringBoot2和Spring5以及WebFlux反应式启动器的反应式微服务 我面临以下问题:我想处理从调用另一个REST服务收到的所有HTTP状态,并在收到一些错误的HTTP状态时抛出异常。例如,当我调用一个端点并收到404 HTTP状态时,我想抛出一个异常,并在某个ExceptionHandler类中处理该异常,就像Spring 4中使用@ControllerAdvice时一样 正确的方法是什么?希望收到一些好的建议 我想你要找的是WebFluxResponseSta

我正在开发一些使用SpringBoot2和Spring5以及WebFlux反应式启动器的反应式微服务

我面临以下问题:我想处理从调用另一个REST服务收到的所有HTTP状态,并在收到一些错误的HTTP状态时抛出异常。例如,当我调用一个端点并收到404 HTTP状态时,我想抛出一个异常,并在某个ExceptionHandler类中处理该异常,就像Spring 4中使用
@ControllerAdvice
时一样


正确的方法是什么?希望收到一些好的建议

我想你要找的是
WebFluxResponseStatusExceptionHandler
检查这个

在WebHandler API中,可以使用WebExceptionHandler来处理 WebFilter和目标WebHandler链中的异常。 使用WebFlux配置时,注册WebExceptionHandler如下 简单到将其声明为Springbean,并可选地表示 通过bean声明上的@Order或通过实现 命令

可能会有帮助,但我自己没有试过

@Component
@Order(-2)
class RestWebExceptionHandler implements WebExceptionHandler{

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        if (ex instanceof PostNotFoundException) {
            exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);

            // marks the response as complete and forbids writing to it
            return exchange.getResponse().setComplete();
        }
        return Mono.error(ex);
    }
}

class PostNotFoundException extends RuntimeException {
    PostNotFoundException(String id) {
        super("Post:" + id + " is not found.");
    }
}
@组件
@订单(-2)
类RestWebExceptionHandler实现WebExceptionHandler{
@凌驾
公共Mono句柄(ServerWebExchange,Throwable-ex){
如果(例如PostNotFoundException的实例){
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
//将响应标记为完整,并禁止对其进行写入
返回exchange.getResponse().setComplete();
}
返回单声道错误(ex);
}
}
类PostNotFoundException扩展了RuntimeException{
PostNotFoundException(字符串id){
超级(“Post:“+id+”未找到”);
}
}

这可以通过两个独立的部分来解决

如何将WebClient接收到的HTTP 404响应转换为自定义异常 使用
WebClient
时,您可以从远程服务接收HTTP 404响应。默认情况下,所有
4xx
5xx
客户端响应将转换为
WebClientResponseException
。因此,您可以在WebFlux应用程序中直接处理这些异常

如果只想将404响应转换为自定义异常,可以执行以下操作:

WebClient webClient = //...
webClient.get().uri("/persons/1")
  .retrieve()
  .onStatus(httpStatus -> HttpStatus.NOT_FOUND.equals(httpStatus),
                        clientResponse -> Mono.error(new MyCustomException()))
  .bodyToMono(...);
这显然是在每个客户端调用的基础上完成的

您可以使用
ExchangeFilterFunction
以更可重用的方式实现同样的功能,您可以在
WebClient
实例上一次性设置该功能,如下所示:

WebClient.builder().filter(myExchangeFilterFunction)...
如何处理WebFlux应用程序中的自定义异常 使用带注释的SpringWebFlux,您可以使用带有
@ExceptionHandler
注释的方法处理异常(请参阅)


注意:使用
WebExceptionHandler
是可能的,但它的级别非常低,因为您在那里没有高级支持:您需要使用缓冲区手动编写响应,而不支持序列化

是的,你说得对。我已经找到了,但是我没有看到它的任何实现。你能给我提供这样的东西吗?我想这会适合我的问题。@parnilsson,谢谢你的例子。对于正在为此而挣扎的人,上面的示例将有助于添加状态代码。如果还想添加消息,请添加:```(serverWebExchange,exception)->{exchange.getResponse().setStatusCode(myStatusGivenTheException);byte[]bytes=“Some text”。getBytes(StandardCharsets.UTF8);DataBuffer buffer=exchange.getResponse().bufferFactory().wrap(字节);return exchange.getResponse().writeWith(Flux.just(buffer))}``您也可以引用-您也可以引用,回答得很好,但是您能否提供更多详细信息,说明如何在ExchangeFilter函数中获取远程服务的异常消息?一段时间以来,我一直在努力解决这个问题,但没有成功。我认为这将非常有帮助,并将提供一个更详细的答案。我不明白-您不会从远程服务获得异常消息,您只会得到一个HTTP响应。也许这应该是一个新问题?哦,是的,对不起。我的意思是,一旦您得到一个状态代码为4xx或5xx的响应,并尝试在ExchangeFilter函数中处理它,您如何准确地获得响应的主体(实际上包含错误消息)?正如您所指出的,我希望在WebClient中处理所有未成功的请求,而不是每次客户端调用。在非Webflux应用程序中如何处理
WebClient响应异常
?我的理解是,
@ExceptionHandler
仅在控制器中受支持。您能在另一个问题中问这个问题吗?在评论中回答是不容易的。