Cor*_*ryO 11 java spring-webflux
尝试根据返回的状态码引发异常时,如何检索响应主体?例如,假设我要抛出异常并拒绝HTTP 201。
client.post().exchange().doOnSuccess(response -> {
if (response.statusCode().value() == 201) {
throw new RuntimeException();
}
}
Run Code Online (Sandbox Code Playgroud)
我如何用响应的正文填充异常,以便抛出详细信息WebClientResponseException?
我应该使用其他方法来测试响应状态代码吗?
编辑:我试图在使用时复制以下功能exchange()。
client.get()
.retrieve()
.onStatus(s -> !HttpStatus.CREATED.equals(s),
MyClass::createResponseException);
//MyClass
public static Mono<WebClientResponseException> createResponseException(ClientResponse response) {
return response.body(BodyExtractors.toDataBuffers())
.reduce(DataBuffer::write)
.map(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
return bytes;
})
.defaultIfEmpty(new byte[0])
.map(bodyBytes -> {
String msg = String.format("ClientResponse has erroneous status code: %d %s", response.statusCode().value(),
response.statusCode().getReasonPhrase());
Charset charset = response.headers().contentType()
.map(MimeType::getCharset)
.orElse(StandardCharsets.ISO_8859_1);
return new WebClientResponseException(msg,
response.statusCode().value(),
response.statusCode().getReasonPhrase(),
response.headers().asHttpHeaders(),
bodyBytes,
charset
);
});
}
Run Code Online (Sandbox Code Playgroud)
ROC*_*CKY 10
您可以通过具有自定义的ExchangeFilterFunction并在构建WebClient之前将其与WebClient.Builder挂钩来实现此目的。
public static ExchangeFilterFunction errorHandlingFilter() {
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
if(clientResponse.statusCode()!=null && (clientResponse.statusCode().is5xxServerError() || clientResponse.statusCode().is4xxClientError()) ) {
return clientResponse.bodyToMono(String.class)
.flatMap(errorBody -> {
return Mono.error(new CustomWebClientResponseException(errorBody,clientResponse.statusCode()));
});
}else {
return Mono.just(clientResponse);
}
});
}
Run Code Online (Sandbox Code Playgroud)
您可以像这样使用上面的代码:
WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(clientOptions))
.defaultHeader(HttpHeaders.USER_AGENT, "Application")
.filter(WebClientUtil.errorHandlingFilter())
.baseUrl("https://httpbin.org/")
.build()
.post()
.uri("/post")
.body(BodyInserters.fromObject(customObjectReference) )
.exchange()
.flatMap(response -> response.toEntity(String.class) );
Run Code Online (Sandbox Code Playgroud)
因此,任何4XX或5XX HttpResponse实际上都会引发CustomWebClientResponseException,您可以配置一些全局异常处理程序,并执行此操作。使用ExchangeFilterFunction的Atleast,您可以在全局位置处理此类事情,也可以添加自定义标头和其他内容。
doOn** 运算符是副作用运算符,例如,应用于记录目的。
在这里,您想在管道级别上实现该行为,因此onStatus此处更合适:
Mono<ClientHttpResponse> clientResponse = client.post().uri("/resource")
.retrieve()
.onStatus(httpStatus -> HttpStatus.CREATED.equals(httpStatus),
response -> response.bodyToMono(String.class).map(body -> new MyException(body)))
bodyToXYZ(...);
Run Code Online (Sandbox Code Playgroud)
要么
Mono<ResponseEntity<String>> result = client.post().uri("/resource")
.exchange()
.flatMap(response -> response.toEntity(String.class))
.flatMap(entity -> {
// return Mono.just(entity) or Mono.error() depending on the response
});
Run Code Online (Sandbox Code Playgroud)
请注意,如果您希望获得较大的响应主体,则获得整个响应主体可能不是一个好主意;在这种情况下,您将在内存中缓冲大量数据。