JavaRush /Курсы /Spring /REST клиенты

REST клиенты

Spring
6 уровень , 0 лекция
Открыта

RestTemplate предусматривает API более высокого уровня в отличие от клиентских библиотек HTTP. Он позволяет с легкостью вызывать конечные точки REST в одной строке. Он раскрывает следующие группы перегруженных методов:

Таблица 1. Методы RestTemplate
Группа методов Описание

getForObject

Получает представление через метод GET.

getForEntity

Получает ResponseEntity (то есть статус, заголовки и тело) через GET.

headForHeaders

Получает все заголовки для ресурса через метод HEAD.

postForLocation

Создает новый ресурс через метод POST и возвращает заголовок Location из ответа.

postForObject

Создает новый ресурс через метод POST и возвращает представление из ответа.

postForEntity

Создает новый ресурс через метод POST и возвращает представление из ответа.

put

Создает или обновляет ресурс через метод PUT.

patchForObject

Обновляет ресурс через метод PATCH и возвращает представление из ответа. Обратите внимание, что HttpURLConnection из JDK не поддерживает метод PATCH, но Apache HttpComponents и другие – поддерживают.

delete

Удаляет ресурсы по указанному URI-идентификатору через метод DELETE.

optionsForAllow

Получает допустимые HTTP-методы для ресурса через метод ALLOW.

exchange

Более обобщенная (и менее консервативная) версия предыдущих методов, которая обеспечивает дополнительную гибкость, если это необходимо. Он принимает RequestEntity (включая HTTP-метод, URL-адрес, заголовки и тело в качестве вводных данных) и возвращает ResponseEntity.

Эти методы позволяют использовать ParameterizedTypeReference вместо Class для задания типа ответа с помощью дженериков.

execute

Наиболее обобщенный способ выполнения запроса, с полным контролем над подготовкой запроса и извлечением ответа через интерфейсы обратного вызова.

Инициализация

Конструктор по умолчанию использует java.net.HttpURLConnection для выполнения запросов. Можно перейти на другую HTTP-библиотеку с реализацией ClientHttpRequestFactory. Имеется встроенная поддержка для:

  • Apache HttpComponents

  • Netty

  • OkHttp

Например, чтобы перейти на Apache HttpComponents, можно сделать следующее:

RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

Каждая ClientHttpRequestFactory открывает параметры конфигурации, специфичные для базовой клиентской HTTP-библиотеки – например, для учетных данных, пула соединений и другой информации.

Обратите внимание, что реализация java.net для HTTP-запросов может привести к исключению при доступе к статусу ответа, который представляет собой ошибку (например, 401). Если это проблема, то переключитесь на другую HTTP-библиотеку клиента.

URI-идентификаторы

Многие методы RestTemplate принимают URI-шаблон и переменные URI-шаблона либо как аргумент переменной String, либо как Map<String,String>.

В следующем примере используется аргумент переменной String:

String result = restTemplate.getForObject(
        "https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");

В следующем примере используется Map<String, String>:

Map<String, String> vars = Collections.singletonMap("hotel", "42");
String result = restTemplate.getForObject(
        "https://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);

Помните, что URI-шаблоны автоматически кодируются, как показано в следующем примере:

restTemplate.getForObject("https://example.com/hotel list", String.class);
// Результат запроса по "https://example.com/hotel%20list"

Можно использовать свойство uriTemplateHandler шаблона RestTemplate для настройки кодирования URI-идентификаторов. Кроме того, можно подготовить java.net.URI и передать его в один из методов RestTemplate, который принимает URI.

Подробнее о работе с URI-идентификаторами и их кодировании см. в разделе "URI-ссылки".

Заголовки

Вы можете использовать методы exchange() для задания заголовков запроса, как показано в следующем примере:

String uriTemplate = "https://example.com/hotels/{hotel}";
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42);
RequestEntity<Void> requestEntity = RequestEntity.get(uri)
        .header("MyRequestHeader", "MyValue")
        .build();
ResponseEntity<String> response = template.exchange(requestEntity, String.class); 
String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
String body = response.getBody();

Можно получать заголовки ответа через множество вариантов методов RestTemplate, которые возвращают ResponseEntity.

Тело

Объекты, передаваемые в методы RestTemplate и возвращаемые из них, преобразуются в сырое содержимое и обратно с помощью HttpMessageConverter.

При методе POST объект ввода сериализуется в тело запроса, как показано в следующем примере:

URI location = template.postForLocation("https://example.com/people", person);

Вам не нужно явно устанавливать заголовок Content-Type для запроса. В большинстве случаев можно найти совместимый преобразователь сообщений на основе типа исходного Object, и выбранный преобразователь сообщений будет устанавливать тип содержимого соответствующим образом. Если необходимо, то можно использовать методы exchange, чтобы явно указать заголовок запроса Content-Type, а это, в свою очередь, влияет на то, какой преобразователь сообщений будет выбран.

При методе GET тело ответа десериализуется в Object вывода, как показано в следующем примере:

Person person = restTemplate.getForObject("https://example.com/people/{id}", Person.class, 42);

Заголовок Accept запроса явно устанавливать не требуется. В большинстве случаев на основе ожидаемого типа ответа можно найти совместимый преобразователь сообщений, который затем поможет заполнить заголовок Accept. При необходимости можно использовать методы exchange для явного указания заголовка Accept.

По умолчанию RestTemplate регистрирует все встроенные преобразователи сообщений в зависимости от результатов проверок classpath, которые помогают определить, какие дополнительные библиотеки преобразования присутствуют. Вы также можете задать используемые преобразователи сообщений явным образом.

Преобразование сообщений

Модуль spring-web содержит контракт HttpMessageConverter для чтения и записи тела HTTP-запросов и ответов через InputStream и OutputStream. Экземпляры HttpMessageConverter используются на стороне клиента (например, в RestTemplate) и на стороне сервера (например, в REST-контроллерах Spring MVC).

Конкретные реализации для основных типов медиа (MIME) предусмотрены во фреймворке и по умолчанию регистрируются в RestTemplate на стороне клиента и в RequestMappingHandlerAdapter на стороне сервера.

Реализации HttpMessageConverter описаны в следующих разделах. Для всех преобразователей используется тип среды передачи данных по умолчанию, но вы можете переопределить его, установив свойство бина supportedMediaTypes. В следующей таблице описана каждая реализация:

Таблица 2. Реализации HttpMessageConverter
MessageConverter Описание

StringHttpMessageConverter

Реализация HttpMessageConverter, которая способна читать и записывать экземпляры String из запроса и ответа HTTP. По умолчанию этот преобразователь поддерживает все типы текстовых сред передачи данных (text/*) и записывает их под заголовком Content-Type для text/plain.

FormHttpMessageConverter

Реализация HttpMessageConverter, которая может читать и записывать данные формы из HTTP-запроса и ответа. По умолчанию этот преобразователь читает и записывает тип среды передачи данных application/x-www-form-urlencoded. Данные формы считываются из и записываются в MultiValueMap<String, String>. Преобразователь также может записывать (но не читать) многокомпонентные данные, считанные из MultiValueMap<String, Object>. По умолчанию поддерживается multipart/form-data. Начиная с версии Spring Framework 5.2, для записи данных формы могут поддерживаться дополнительные многокомпонентные подтипы. Для получения более подробной информации обратитесь к javadoc по FormHttpMessageConverter.

ByteArrayHttpMessageConverter

Реализация HttpMessageConverter, которая способна читать и записывать байтовые массивы из запроса и ответа HTTP. По умолчанию этот преобразователь поддерживает все типы сред передачи данных (*/*) и записывает их под заголовком Content-Type для application/octet-stream. Можно переопределить это, установив свойство supportedMediaTypes и переопределив getContentType(byte[]).

MarshallingHttpMessageConverter

Реализация HttpMessageConverter, которая способна читать и записывать XML, используя абстракции Marshaller и Unmarshaller из Spring, находящиеся в пакете org.springframework.oxm. Для использования этого преобразователя требуется наличие Marshaller и Unmarshaller. Вы можете внедрить их через конструктор или свойства бина. По умолчанию конвертер поддерживает форматы text/xml и application/xml.

MappingJackson2HttpMessageConverter

An HttpMessageConverter implementation that can read and write JSON by using Jackson’s ObjectMapper. You can customize JSON mapping as needed through the use of Jackson’s provided annotations. When you need further control (for cases where custom JSON serializers/deserializers need to be provided for specific types), you can inject a custom ObjectMapper through the ObjectMapper property. By default, this converter supports application/json.

MappingJackson2XmlHttpMessageConverter

Реализация HttpMessageConverter, которая способна читать и записывать XML с помощью XmlMapper расширения Jackson XML. Вы можете настраивать XML-отображение по мере необходимости с помощью JAXB или аннотаций, предоставляемых библиотекой Jackson. Если вам нужен дополнительный контроль (в случаях, когда необходимо предоставить пользовательские сериализаторы/десериализаторы XML для определенных типов), вы можете внедрить кастомный XmlMapper через свойство ObjectMapper. По умолчанию преобразователь поддерживает формат application/xml.

SourceHttpMessageConverter

Реализация HttpMessageConverter, которая способна читать и записывать javax.xml.transform.Source из запроса и ответа HTTP. Поддерживаются только DOMSource, SAXSource и StreamSource. По умолчанию конвертер поддерживает форматы text/xml и application/xml.

BufferedImageHttpMessageConverter

Реализация HttpMessageConverter, которая способна читать и записывать java.awt.image.BufferedImage из запроса и ответа HTTP. Этот преобразователь считывает и записывает тип среды передачи данных, поддерживаемый API ввода-вывода Java.

Представления Jackson JSON

Можно задавать Представление в формате JSON через билиотеку Jackson для сериализации исключительно подмножества свойств объекта, как показано в следующем примере:

MappingJacksonValue value = new MappingJacksonValue(new User("eric", "7!jd#h23"));
value.setSerializationView(User.WithoutPasswordView.class);
RequestEntity<MappingJacksonValue> requestEntity =
    RequestEntity.post(new URI("https://example.com/user")).body(value);
ResponseEntity<String> response = template.exchange(requestEntity, String.class);

Многокомпонентность

Для отправки многокомпонентных данных необходимо предоставить MultiValueMap<String, Object>, значениями которого могут быть Object для содержимого компонента, Resource для файлового компонента или HttpEntity для содержимого компонента с заголовками. Например:

MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("fieldPart", "fieldValue");
parts.add("filePart", new FileSystemResource("...logo.png"));
parts.add("jsonPart", new Person("Jason"));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
parts.add("xmlPart", new HttpEntity<>(myBean, headers));

В большинстве случаев не требуется задавать Content-Type для каждого компонента. Тип содержимого определяется автоматически на основе HttpMessageWriter, выбранного для сериализации, или, в случае Resource, на основе расширения файла. При необходимости можно явно указать MediaType с использованием функции-обёртки HttpEntity.

Когда MultiValueMap будет готова, можно передать ее в RestTemplate, как показано ниже:

MultiValueMap<String, Object> parts = ...;
template.postForObject("https://example.com/upload", parts, Void.class);

Если MultiValueMap содержит хотя бы одно не-String значение, то Content-Type устанавливается в multipart/form-data с помощью FormHttpMessageConverter. Если MultiValueMap имеет String значения, то Content-Type по умолчанию принимает значение application/x-www-form-urlencoded. При необходимости Content-Type также можно задать явным образом.

Использование шаблона AsyncRestTemplate (устарело)

Шаблон AsyncRestTemplate является устаревшим. Во всех случаях, предусматривающих использование AsyncRestTemplate, используйте WebClient.

Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
чеснок Уровень 6
13 мая 2023
а задачки то будут?