Как извлечь заголовок ответа и код состояния из Spring 5 WebClient ClientResponse

Я новичок в Spring Reactive framework и пытаюсь преобразовать код Springboot 1.5.x в Springboot 2.0. Мне нужно вернуть заголовок ответа после некоторой фильтрации, кода тела и состояния из Spring 5 WebClient ClientResponse. Я не хочу использовать метод block (), поскольку он преобразует его в вызов синхронизации. Я могу довольно легко получить responsebody с помощью bodyToMono. Кроме того, я получаю код состояния, заголовки и текст, если я просто возвращаю ClientResponse, но мне нужно обработать ответ на основе параметров statusCode и заголовка. Я пробовал подписаться, FlatMap и т. д., Но ничего не работает.

Например. - Код ниже вернет тело ответа

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

Но подобная парадигма не работает для получения заголовков statusCode и Response. Может ли кто-нибудь помочь мне в извлечении параметров statusCode и заголовка с использованием реактивной среды Spring 5.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
24
0
35 203
6

Ответы 6

Вы можете использовать функцию обмена веб-клиента, например.

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 и т. д.

Но это просто печатает код HttpStatus. Что, если мне нужно вернуть его значение? Возможно ли это?

C96 17.07.2020 00:39

Это должно быть отмечено как принятый ответ! У меня сработало, спасибо!

actunderdc 13.11.2020 12:04

@ C96 это асинхронные вызовы, поэтому вы не можете возвращать значения в традиционном смысле. Вы можете вернуть только Mono и Flux. Выполните обработку внутри метода doOnSuccess.

thisisshantzz 15.12.2020 00:20

@thisishantzz, не могли бы вы привести мне пример?

C96 15.12.2020 14:40

Мне нужно было проверить детали ответа (заголовки, статус и т. д.) И тело.

Единственный способ сделать это - использовать .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
    });

Я надеюсь, что это помогает. Если кто-то знает, как это сделать лучше, сообщите нам об этом.

Как я могу прочитать код состояния внутри этого метода subscribe () -> {}? Мол, если мне нужно передать код состояния другому методу

C96 16.07.2020 22:44

Вы можете настроить spring boot> = 2.1.0 для регистрации запросов и ответов, если вы используете WebClient:

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

Как описано в документации по загрузке спринта, если вы хотите, чтобы заголовки тоже регистрировались, вы должны добавить

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

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

Но имейте в виду, что это может регистрировать чувствительную информацию.

Спрашивающий говорит ... Мне нужно обработать ответ на основе параметров statusCode и заголовка.. Но код, который вы предоставили, предназначен для конфигурации журнала, что означает, что он бесполезен в контексте вопроса. Следовательно -1.

Adindu Stevens 17.03.2019 13:14

@AdinduStevens, мне жаль, что я не понял этого из вопроса. Я оставлю здесь ответ на тот случай, если кто-то приземлится здесь и захочет зарегистрировать только кодировщик состояния и параметры заголовка.

Tobske 18.03.2019 12:55

Для кода состояния вы можете попробовать следующее:

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

Как мне распечатать значение "статуса"? Как просто "200", а не весь объект Mono <>

C96 16.07.2020 22:52

После 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)));
 httpClient
            .get()
            .uri(url)
            .retrieve()
            .toBodilessEntity()
            .map(reponse -> Tuple2(reponse.statusCode, reponse.headers))

Другие вопросы по теме