我使用webflux Mono(在Spring boot 5中)使用外部API。当API响应状态代码为200时,我能够很好地获取数据,但是当API返回错误时,我无法从API检索错误消息。 Spring webclient错误处理程序始终将消息显示为
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"
}
}
我使用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的错误时,如何才能访问JSON响应?
答案 0 :(得分:4)
就像@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,这将使我的错误处理更容易在不同情况下
答案 1 :(得分:4)
如果要检索错误详细信息:
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
类映射错误正文
每请求变体:
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;
})
答案 2 :(得分:3)
查看.onErrorMap()
,这会让您看到异常。因为您可能还需要查看exchange()的body(),所以不要使用retrieve,而是
.exchange().flatMap((ClientResponse) response -> ....);