java - WebFlux WebClient中测试状态码时如何获取响应体?

标签 java spring-webflux

当试图根据返回的状态代码抛出异常时,如何检索响应主体?例如,假设我想抛出异常并拒绝 HTTP 201。

client.post().exchange().doOnSuccess(response -> {
    if (response.statusCode().value() == 201) {
        throw new RuntimeException();
    }
}

如何使用响应主体填充异常,以便抛出详细的 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
                        );
            });
}

最佳答案

您可以通过自定义 ExchangeFilterFunction 然后在构建 WebClient 之前将其与 WebClient.Builder Hook 来实现这一点。

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

你可以像这样使用上面的内容:

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

因此任何 4XX 或 5XX HttpResponse 实际上都会抛出 CustomWebClientResponseException 并且您可以配置一些全局异常处理程序并用它做您喜欢的事情。至少使用 ExchangeFilterFunction 你可以在全局范围内处理这样的事情或者添加自定义 header 和东西。

关于java - WebFlux WebClient中测试状态码时如何获取响应体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46759603/

相关文章:

java - 如何让Java驱动/控制webkit/gecko?

spring-boot - 如何处理webclient抛出的异常?

java - Mono.flatMap 没有被调用

spring - 使用 webflux 处理异常并返回正确的 HTTP 代码

spring-boot - 当我在响应正文中返回值时,Spring WebFlux 抛出 'producer' 类型未知

spring-webflux - 将 ClientResponse 转换为 ServerResponse

java - 没有为命名空间 [/] 映射的操作和与上下文路径 [/SampleTC_test] 关联的操作名称 [viewBooks]。 - [未知位置]

java - Java FileInputStream 是否为写入锁定文件

java - 读取RequestMapping注解值

java - 我应该如何使用 JAR 文件为 Amazon S3 存储桶(动态 IP 地址 CDN)配置我的 JNLP 文件?