Как получить ответ json от Spring WebClient - PullRequest
0 голосов
/ 09 июля 2020

Я пытался следовать простейшим учебным пособиям по использованию WebClient, который, как я понимаю, является следующим лучшим по сравнению с RestTemplate.

Например, https://www.baeldung.com/spring-5-webclient#4 -getting-a-response

enter image description here

So when I try to do the same thing with https://petstore.swagger.io/v2/pet/findByStatus?status=available, который должен вернуть некоторые json,

WebClient webClient = WebClient.create();
webClient.get().uri("https://petstore.swagger.io/v2/pet/findByStatus?status=available").exchange().block();

введите описание изображения здесь

Я совершенно не знаю, как исходить из полученного объекта DefaultClientResponse. Это не должно быть таким запутанным, чтобы добраться до тела физического ответа, но я отвлекся.

Как мне получить тело ответа с предоставленным мной кодом?

Ответы [ 2 ]

2 голосов
/ 12 июля 2020

В форме, которая у вас есть в настоящее время, и объясняя поведение ..

WebClient webClient = WebClient.create();
webClient.get()
         .uri("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
         .exchange()
         .block();

block() запускает запрос, внутренне синхронно подписываясь на Mono, и возвращает результат ClientResponse . Вы также можете обработать это асинхронно, вызвав subscribe() в Mono, возвращаемом методом exchange(), вместо block().

В этой текущей форме после block() у вас теперь есть все метаданные (ie. из заголовка ответа) об ответе в объекте ClientResponse, включая статус успеха. Это не означает, что тело ответа перестало поступать. Если вас не интересует полезная нагрузка ответа, вы можете подтвердить успех и оставить все как есть.

Если вы хотите дополнительно посмотреть тело ответа, вам нужно преобразовать поток тела ответа в некоторый класс . На этом этапе вы можете решить, хотите ли вы прочитать все в одном Mono с bodyToMono или в поток объектов (Flux) с bodyToFlux, например, в случае, когда ответом является JSON массив, который может быть проанализирован на отдельные отдельные объекты Java.

Однако в вашем случае вы просто хотите видеть JSON как есть. Так что преобразования в String достаточно. Вы могли бы просто использовать bodyToMono, который вернет объект Mono.

WebClient webClient = WebClient.create();
String responseJson = webClient.get()
                               .uri("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
                               .exchange()
                               .block()
                               .bodyToMono(String.class)
                               .block();

Здесь вы используете block(), чтобы дождаться прибытия полезной нагрузки ответа и ее синтаксического анализа в String, но вы также можно subscribe в Mono, чтобы получить его в ответ, когда он будет завершен.

Следует отметить, что retrieve() можно использовать вместо exchange() для ярлыка ClientResponse. В этом случае вы позволяете поведению по умолчанию обрабатывать ответы об ошибках. Использование exchange() возлагает всю ответственность на приложение за реагирование на сообщения об ошибках на ClientResponse. Подробнее в Javado c. Версия retrieve() будет выглядеть следующим образом. Не нужно набирать block(), поскольку вас интересуют только данные ответа.

WebClient webClient = WebClient.create();
String responseJson = webClient.get()
                               .uri("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
                               .retrieve()
                               .bodyToMono(String.class)
                               .block();
0 голосов
/ 09 июля 2020

Все это не интуитивно понятно. Обычно я не играю с запросами в мире Java, но этой библиотеке WebClient честно не хватает интуитивного потока. Например, когда я читаю код, могу ли я, как средний разработчик, сказать, что вообще происходит? Могу ли я сделать разумные предположения о том, как использовать библиотеку, не обращаясь к документации?

Вот как вы делаете запрос с RestTemplate

String json = new RestTemplate()
    .getForEntity("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
    .getBody();

Вот как вы запрос с помощью requests

import requests

json = requests.get("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
    .content

Вот как вы делаете запрос с помощью WebClient

String json = WebClient.create()
    .get()
    .uri("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
    .exchange()
    .block()
    .bodyToMono(String.class)
    .block();

Я не уверен, почему «новые» и «модные» запросы Spring библиотека должна быть уродливой, нечитаемой и неинтуитивной, но, по крайней мере, она может делать запросы.

...