spring 在Sping Boot 中使用Web客户端Mono获取API响应错误消息

pftdvrlh  于 2023-03-16  发布在  Spring
关注(0)|答案(4)|浏览(200)

我正在使用webflux Mono(在Sping Boot 5中)来使用外部API。当API响应状态代码为200时,我可以很好地获取数据,但当API返回错误时,我无法从API中检索错误消息。Spring webclient错误处理程序总是将消息显示为
ClientResponse has erroneous status code: 500 Internal Server Error,但当我使用PostMan时,API返回此JSON响应,状态代码为500。

{
 "error": {
    "statusCode": 500,
    "name": "Error",
    "message":"Failed to add object with ID:900 as the object exists",
    "stack":"some long message"
   }
}

我使用WebClient的请求如下

webClient.getWebClient()
            .post()
            .uri("/api/Card")
            .body(BodyInserters.fromObject(cardObject))
            .retrieve()
            .bodyToMono(String.class)
            .doOnSuccess( args -> {
                System.out.println(args.toString());
            })
            .doOnError( e ->{
                e.printStackTrace();
                System.out.println("Some Error Happend :"+e);
            });

我的问题是,当API返回一个状态代码为500的Error时,我如何访问JSON响应?

rfbsl7qr

rfbsl7qr1#

如果要检索错误详细信息:

WebClient webClient = WebClient.builder()
    .filter(ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
        if (clientResponse.statusCode().isError()) {
            return clientResponse.bodyToMono(ErrorDetails.class)
                    .flatMap(errorDetails -> Mono.error(new CustomClientException(clientResponse.statusCode(), errorDetails)));
        }
        return Mono.just(clientResponse);
    }))
    .build();

class CustomClientException extends WebClientException {
    private final HttpStatus status;
    private final ErrorDetails details;

    CustomClientException(HttpStatus status, ErrorDetails details) {
        super(status.getReasonPhrase());
        this.status = status;
        this.details = details;
    }

    public HttpStatus getStatus() {
        return status;
    }

    public ErrorDetails getDetails() {
        return details;
    }
}

并且ErrorDetails类Map错误体
按请求变量:

webClient.get()
    .exchange()
    .map(clientResponse -> {
        if (clientResponse.statusCode().isError()) {
            return clientResponse.bodyToMono(ErrorDetails.class)
                    .flatMap(errorDetails -> Mono.error(new CustomClientException(clientResponse.statusCode(), errorDetails)));
        }
        return clientResponse;
    })
kupeojn6

kupeojn62#

正如@Frischling建议的那样,我将请求更改为如下所示

return webClient.getWebClient()
 .post()
 .uri("/api/Card")
 .body(BodyInserters.fromObject(cardObject))
 .exchange()
 .flatMap(clientResponse -> {
     if (clientResponse.statusCode().is5xxServerError()) {
        clientResponse.body((clientHttpResponse, context) -> {
           return clientHttpResponse.getBody();
        });
     return clientResponse.bodyToMono(String.class);
   }
   else
     return clientResponse.bodyToMono(String.class);
});

我还注意到有几个状态代码,从1xx到5xx,这将使我在不同情况下的错误处理更容易

inb24sb2

inb24sb23#

看一下.onErrorMap(),它为您提供了要查看的异常。由于您可能还需要查看exchange()的body(),因此不要使用retrieve,而是

.exchange().flatMap((ClientResponse) response -> ....);
ppcbkaq5

ppcbkaq54#

我也在纠结这个问题
执行此操作以获取字符串形式的body

.retrieve()
.onStatus(HttpStatus::isError, clientResponse -> {
               clientResponse.bodyToMono(String.class).blockOptional().ifPresent(log::info);
                return Mono.error(RuntimeException::new);})

这是我找到的解决办法。

相关问题