简体   繁体   English

在Spring Boot中使用Web Client Mono获取API响应错误消息

[英]Get API response error message using Web Client Mono in Spring Boot

I am using webflux Mono (in Spring boot 5) to consume an external API. 我使用webflux Mono(在Spring boot 5中)使用外部API。 I am able to get data well when the API response status code is 200, but when the API returns an error I am not able to retrieve the error message from the API. 当API响应状态代码为200时,我能够很好地获取数据,但是当API返回错误时,我无法从API检索错误消息。 Spring webclient error handler always display the message as Spring webclient错误处理程序始终将消息显示为

ClientResponse has erroneous status code: 500 Internal Server Error , but when I use PostMan the API returns this JSON response with status code 500. ClientResponse has erroneous status code: 500 Internal Server Error ,但是当我使用PostMan时,API会返回状态代码为500的JSON响应。

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

My request using WebClient is as follows 我使用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);
            });

My question is, how can I get access to the JSON response when the API returns an Error with status code of 500? 我的问题是,当API返回状态代码为500的错误时,如何才能访问JSON响应?

If you want to retrieve the error details: 如果要检索错误详细信息:

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();

with

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;
    }
}

and with the ErrorDetails class mapping the error body 并使用ErrorDetails类映射错误体

Per-request variant: 每请求变体:

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;
    })

Just as @Frischling suggested, I changed my request to look as follows 就像@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);
});

I also noted that there's a couple of status codes from 1xx to 5xx, which is going to make my error handling easier for different cases 我还注意到有一些从1xx到5xx的状态代码,这将使我的错误处理更容易在不同的情况下

Look at .onErrorMap() , that gives you the exception to look at. 查看.onErrorMap() ,它为您提供了查看的异常。 Since you might also need the body() of the exchange() to look at, don't use retrieve, but 因为您可能还需要查看exchange()的body(),所以不要使用retrieve,而是

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM