【发布时间】:2022-08-23 06:36:17
【问题描述】:
tbjorch\ 的回答使我走上了正确的道路,但我发现的一件事是我应该为HttpClientErrorException 和HttpServerErrorException 使用静态.create 方法构造HTTP 异常。如果我不这样做,我的所有异常都将作为Exception 超类抛出,这是不可取的,因为它丢失了原始 Http 状态代码的上下文。
我是使用 Spring WebClient 的新手。我正在实现的 API 根据成功或失败使用不同的 JSON 结构进行响应。在失败的情况下,我希望能够反序列化响应正文并返回错误消息。根据下面的代码,我收到一条错误消息:
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83)
我同意,在 2 个地方屏蔽是没有意义的。但我不明白如何反序列化错误响应以获取错误消息。我在网上和 StackOverflow 上读到的所有内容都表明人们只是返回 Mono.error 或抛出异常,但在这些情况下他们似乎没有反序列化响应正文。这是我的代码:
public boolean updatePassword(String id, String data) {
final var responseSpec =
client
.post()
.uri(builder -> builder.path(\"/{id}/change_password\").build(id))
.header(HttpHeaders.AUTHORIZATION, \"Bearer \" + staticData.getAPIToken())
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(data))
.retrieve()
.onStatus(
HttpStatus::isError,
error -> {
final var errorResponse = error.bodyToMono(ErrorResponse.class).block();
final var errorMsg = errorResponse.getCause().getSummary();
if (error.statusCode().is4xxClientError()) {
throw new HttpClientErrorException(error.statusCode(), errorMsg);
}
if (error.statusCode().is5xxServerError()) {
throw new HttpServerErrorException(error.statusCode(), errorMsg);
}
return Mono.error(
new HttpServerErrorException(
HttpStatus.INTERNAL_SERVER_ERROR, \"Something else.\"));
})
.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {});
final var response = responseSpec.block();
return response.containsKey(\"password\") && response.containsKey(\"provider\");
}
PS。我也尝试过使用.exchangeToMono 而不是.retrieve,这样我就可以检查响应状态代码,然后为.bodyToMono 函数使用不同的类型,但是一旦我在成功之间编写了两种不同的类型和失败,我收到一个错误,指出无法推断类型参数。
标签: java spring-boot spring-webclient