adr*_*roy 7 spring reactor spring-webflux
我正在使用spring webflux的webclient,如下所示:
WebClient.create()
.post()
.uri(url)
.syncBody(body)
.accept(MediaType.APPLICATION_JSON)
.headers(headers)
.exchange()
.flatMap(clientResponse -> clientResponse.bodyToMono(tClass));
Run Code Online (Sandbox Code Playgroud)
它运作良好.我现在想要处理来自我正在调用的Web服务的错误(Ex 500内部错误).通常我会在"stream"上添加一个doOnError,而isu是Throwable来测试状态代码,
但我的问题是我想获得webservice提供的正文,因为它为我提供了一条我想要使用的消息.
我希望无论发生什么事情都要做flatMap,并测试自己的状态代码以反序列化或不反复身体.
Oma*_*IDI 22
我更喜欢使用 ClientResponse 提供的方法来处理 http 错误和抛出异常:
WebClient.create()
.post()
.uri( url )
.body( bodyObject == null ? null : BodyInserters.fromValue( bodyObject ) )
.accept( MediaType.APPLICATION_JSON )
.headers( headers )
.exchange()
.flatMap( clientResponse -> {
//Error handling
if ( clientResponse.statusCode().isError() ) { // or clientResponse.statusCode().value() >= 400
return clientResponse.createException().flatMap( Mono::error );
}
return clientResponse.bodyToMono( clazz )
} )
//You can do your checks: doOnError (..), onErrorReturn (..) ...
...
Run Code Online (Sandbox Code Playgroud)
实际上,它与 DefaultWebClient 的 DefaultResponseSpec 中用于处理错误的逻辑相同。DefaultResponseSpec 是 ResponseSpec 的一个实现,如果我们使用retrieve()而不是exchange(),我们就会拥有它。
Wes*_*Gun 16
我们没有onStatus()
吗?
public Mono<Void> cancel(SomeDTO requestDto) {
return webClient.post().uri(SOME_URL)
.body(fromObject(requestDto))
.header("API_KEY", properties.getApiKey())
.retrieve()
.onStatus(HttpStatus::isError, response -> {
logTraceResponse(log, response);
return Mono.error(new IllegalStateException(
String.format("Failed! %s", requestDto.getCartId())
));
})
.bodyToMono(Void.class)
.timeout(timeout);
}
Run Code Online (Sandbox Code Playgroud)
和:
public static void logTraceResponse(Logger log, ClientResponse response) {
if (log.isTraceEnabled()) {
log.trace("Response status: {}", response.statusCode());
log.trace("Response headers: {}", response.headers().asHttpHeaders());
response.bodyToMono(String.class)
.publishOn(Schedulers.elastic())
.subscribe(body -> log.trace("Response body: {}", body));
}
}
Run Code Online (Sandbox Code Playgroud)
Moh*_*ale 14
你也可以这样做
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);
});
Run Code Online (Sandbox Code Playgroud)
阅读这篇文章以获取更多示例链接,当我遇到类似的错误处理问题时,我发现它很有帮助
小智 10
我通过这样做得到了错误正文:
webClient
...
.retrieve()
.onStatus(HttpStatus::isError, response -> response.bodyToMono(String.class) // error body as String or other class
.flatMap(error -> Mono.error(new RuntimeException(error)))) // throw a functional exception
.bodyToMono(MyResponseType.class)
.block();
Run Code Online (Sandbox Code Playgroud)
请注意,在撰写本文时,5xx 错误不再导致底层 Netty 层出现异常。见https://github.com/spring-projects/spring-framework/commit/b0ab84657b712aac59951420f4e9d696c3d84ba2
利用我学到的这个关于“使用 Reactor 抛出异常的正确方法”的精彩答案,我能够将这个答案放在一起。它使用.onStatus
、.bodyToMono
、 和.handle
将错误响应正文映射到异常。
// create a chicken
webClient
.post()
.uri(urlService.getUrl(customer) + "/chickens")
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(chickenCreateDto), ChickenCreateDto.class) // outbound request body
.retrieve()
.onStatus(HttpStatus::isError, clientResponse ->
clientResponse.bodyToMono(ChickenCreateErrorDto.class)
.handle((error, sink) ->
sink.error(new ChickenException(error))
)
)
.bodyToMono(ChickenResponse.class)
.subscribe(
this::recordSuccessfulCreationOfChicken, // accepts ChickenResponse
this::recordUnsuccessfulCreationOfChicken // accepts throwable (ChickenException)
);
Run Code Online (Sandbox Code Playgroud)
我做这样的事情:
Mono<ClientResponse> responseMono = requestSpec.exchange()
.doOnNext(response -> {
HttpStatus httpStatus = response.statusCode();
if (httpStatus.is4xxClientError() || httpStatus.is5xxServerError()) {
throw new WebClientException(
"ClientResponse has erroneous status code: " + httpStatus.value() +
" " + httpStatus.getReasonPhrase());
}
});
Run Code Online (Sandbox Code Playgroud)
然后:
responseMono.subscribe(v -> { }, ex -> processError(ex));
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
13664 次 |
最近记录: |