如何提取响应头和Spring 5 WebClient ClientResponse的状态代码

时间:2018-05-07 23:46:39

标签: spring spring-boot spring-webflux

我是Spring Reactive框架的新手。试图将Springboot 1.5.x代码转换为Springboot 2.0。我需要在一些过滤之后返回响应头,body& Spring 5 WebClient ClientResponse的状态代码。我不想使用block()方法,因为它会将其转换为同步调用。 我可以使用bodyToMono轻松获得响应体。此外,我正在获取状态代码,标题和&如果我只是返回ClientResponse,但我需要处理基于statusCode&的响应。标头参数。 我试过订阅,flatMap等但没有任何作用。

E.g。 - 下面的代码将返回响应正文

Mono<String> responseBody =  response.flatMap(resp -> resp.bodyToMono(String.class));

但类似的范例并不适用于获得statusCode&amp;响应标头。 有人可以帮我提取statusCode&amp;使用Spring 5反应框架的头参数。

7 个答案:

答案 0 :(得分:3)

您可以使用webclient的交换功能,例如

Mono<ClientResponse> reponse = webclient.get()
.uri("https://stackoverflow.com)
.exchange()
.doOnSuccess(clientResponse -> System.out.println("clientResponse.headers() = " + clientResponse.headers()))
.doOnSuccess(clientResponse -> System.out.println("clientResponse.statusCode() = " + clientResponse.statusCode()))
.flatMap(clientResponse -> clientResponse.bodyToMono(String.class));

然后你可以转换bodyToMono等

答案 1 :(得分:3)

在 Spring Boot 2.4.x / Spring 5.3 之后,WebClient exchange 方法被弃用,取而代之的是 retrieve,因此您必须使用 ResponseEntity 获取标头和响应状态,如下例所示:

webClient
        .method(HttpMethod.POST)
        .uri(uriBuilder -> uriBuilder.path(loginUrl).build())
        .bodyValue(new LoginBO(user, passwd))
        .retrieve()
        .toEntity(LoginResponse.class)
        .filter(
            entity ->
                entity.getStatusCode().is2xxSuccessful()
                    && entity.getBody() != null
                    && entity.getBody().isLogin())
        .flatMap(entity -> Mono.justOrEmpty(entity.getHeaders().getFirst(tokenHeader)));

答案 2 :(得分:2)

我还需要检查回复详细信息(标题,状态等)和正文。

我能够做到这一点的唯一方法是将.exchange()与两个subscribe()一起使用,如下例:

    Mono<ClientResponse> clientResponse = WebClient.builder().build()
            .get().uri("https://stackoverflow.com")
            .exchange();

    clientResponse.subscribe((response) -> {

        // here you can access headers and status code
        Headers headers = response.headers();
        HttpStatus stausCode = response.statusCode();

        Mono<String> bodyToMono = response.bodyToMono(String.class);
        // the second subscribe to access the body
        bodyToMono.subscribe((body) -> {

            // here you can access the body
            System.out.println("body:" + body);

            // and you can also access headers and status code if you need
            System.out.println("headers:" + headers.asHttpHeaders());
            System.out.println("stausCode:" + stausCode);

        }, (ex) -> {
            // handle error
        });
    }, (ex) -> {
        // handle network error
    });

我希望它会有所帮助。 如果有人知道更好的方法,请告诉我们。

答案 3 :(得分:1)

有关状态码,您可以尝试以下方法:

Mono<HttpStatus> status = webClient.get()
                .uri("/example")
                .exchange()
                .map(response -> response.statusCode());

对于标题:

Mono<HttpHeaders> result = webClient.get()
                .uri("/example")
                .exchange()
                .map(response -> response.headers().asHttpHeaders());

答案 4 :(得分:0)

如果使用WebClient,则可以配置spring boot> = 2.1.0来记录请求和响应:

spring.http.log-request-details: true
logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions: TRACE

in the sprint boot docs所述,如果您也想记录标头,则必须添加

Consumer<ClientCodecConfigurer> consumer = configurer ->
    configurer.defaultCodecs().enableLoggingRequestDetails(true);

WebClient webClient = WebClient.builder()
    .exchangeStrategies(ExchangeStrategies.builder().codecs(consumer).build())
    .build();

但是请注意,这可以记录敏感信息。

答案 5 :(得分:0)

 httpClient
            .get()
            .uri(url)
            .retrieve()
            .toBodilessEntity()
            .map(reponse -> Tuple2(reponse.statusCode, reponse.headers))

答案 6 :(得分:0)

如上所述,交换已被弃用,因此我们使用了retrieve()。这就是我在提出请求后返回代码的方式。

.then