簡體   English   中英

如何從 Spring 中提取響應 header 和狀態碼 5 WebClient ClientResponse

[英]How to extract response header & status code from Spring 5 WebClient ClientResponse

我是 Spring Reactive 框架的新手,正在嘗試將 Springboot 1.5.x 代碼轉換為 Springboot 2.0。 經過一些過濾后,我需要返回響應 header,來自 Spring 的正文和狀態代碼 5 WebClient ClientResponse。 我不想使用 block() 方法,因為它會將其轉換為同步調用。 我可以使用 bodyToMono 輕松獲得 responsebody。 此外,如果我只是返回 ClientResponse,我將獲得狀態代碼、標頭和正文,但我需要根據 statusCode 和 header 參數處理響應。 我試過訂閱、平面地圖等,但沒有任何效果。

例如 - 下面的代碼將返回響應正文

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

但是類似的范例無法獲取 statusCode 和 Response 標頭。 有人可以幫助我使用 Spring 5 反應框架提取 statusCode 和 header 參數。

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

Mono<String> 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 等

我還需要檢查響應詳細信息(標題、狀態等)和正文。

我能夠做到的唯一方法是使用.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
    });

我希望它有幫助。 如果有人知道更好的方法,請告訴我們。

對於狀態代碼,您可以嘗試以下操作:

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

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

如果您使用WebClient您可以配置 spring boot >= 2.1.0 來記錄請求和響應:

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

正如sprint boot docs 中所描述的,如果您也希望記錄標題,則必須添加

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

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

但請注意,這可能會記錄敏感信息。

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

如上所述,交換已被棄用,因此我們使用了retrieve()。 這就是我在提出請求后返回代碼的方式。

public HttpStatus getResult() {
    WebClient.ResponseSpec response = client
            .get()
            .uri("/hello")
            .accept(MediaType.APPLICATION_JSON)
            .retrieve();

    return Optional.of(response.toBodilessEntity().block().getStatusCode()).get();
}

您可以使用flatMap從 Mono 中提取Mono

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM