Руководство по RestTemplate

1. Обзор

В этом руководстве мы собираемся проиллюстрировать широкий спектр операций, в которых можно правильно использовать Spring REST Client - RestTemplate .

Что касается стороны API всех примеров, мы будем запускать службу RESTful отсюда.

2. Уведомление об устаревании

Начиная с Spring Framework 5, наряду со стеком WebFlux, Spring представила новый HTTP-клиент под названием WebClient .

WebClient - это современный HTTP-клиент, альтернативный RestTemplate . Он не только предоставляет традиционный синхронный API, но также поддерживает эффективный неблокирующий и асинхронный подход.

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

3. Используйте GET для получения ресурсов.

3.1. Получить простой JSON

Давайте начнем с простого и поговорим о запросах GET на коротком примере с использованием API getForEntity () :

RestTemplate restTemplate = new RestTemplate(); String fooResourceUrl = "//localhost:8080/spring-rest/foos"; ResponseEntity response = restTemplate.getForEntity(fooResourceUrl + "/1", String.class); assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));

Обратите внимание, что у нас есть полный доступ к HTTP-ответу , поэтому мы можем делать что-то вроде проверки кода состояния, чтобы убедиться, что операция прошла успешно, или работать с фактическим телом ответа:

ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(response.getBody()); JsonNode name = root.path("name"); assertThat(name.asText(), notNullValue());

Здесь мы работаем с телом ответа как стандартной строкой и используем Jackson (и структуру узла JSON, которую предоставляет Jackson) для проверки некоторых деталей.

3.2. Получение POJO вместо JSON

Мы также можем отобразить ответ напрямую в Resource DTO:

public class Foo implements Serializable { private long id; private String name; // standard getters and setters }

Теперь мы можем просто использовать API getForObject в шаблоне:

Foo foo = restTemplate .getForObject(fooResourceUrl + "/1", Foo.class); assertThat(foo.getName(), notNullValue()); assertThat(foo.getId(), is(1L));

4. Используйте HEAD для получения заголовков.

Давайте теперь быстро рассмотрим использование HEAD, прежде чем переходить к более общим методам.

Мы собираемся использовать здесь API headForHeaders () :

HttpHeaders httpHeaders = restTemplate.headForHeaders(fooResourceUrl); assertTrue(httpHeaders.getContentType().includes(MediaType.APPLICATION_JSON));

5. Используйте POST для создания ресурса.

Чтобы создать новый ресурс в API, мы можем эффективно использовать API postForLocation () , postForObject () или postForEntity () .

Первый возвращает URI вновь созданного ресурса, а второй возвращает сам ресурс.

5.1. PostForObject () API ,

RestTemplate restTemplate = new RestTemplate(); HttpEntity request = new HttpEntity(new Foo("bar")); Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class); assertThat(foo, notNullValue()); assertThat(foo.getName(), is("bar"));

5.2. PostForLocation () API ,

Точно так же давайте посмотрим на операцию, которая вместо возврата полного ресурса просто возвращает Location этого вновь созданного ресурса:

HttpEntity request = new HttpEntity(new Foo("bar")); URI location = restTemplate .postForLocation(fooResourceUrl, request); assertThat(location, notNullValue());

5.3. Обмен () API ,

Давайте посмотрим, как выполнить POST с помощью более общего API обмена :

RestTemplate restTemplate = new RestTemplate(); HttpEntity request = new HttpEntity(new Foo("bar")); ResponseEntity response = restTemplate .exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class); assertThat(response.getStatusCode(), is(HttpStatus.CREATED)); Foo foo = response.getBody(); assertThat(foo, notNullValue()); assertThat(foo.getName(), is("bar")); 

5.4. Отправить данные формы

Далее давайте посмотрим, как отправить форму с помощью метода POST.

Во-первых, нам нужно установить заголовок Content-Type на application / x-www-form-urlencoded.

Это гарантирует, что на сервер может быть отправлена ​​большая строка запроса, содержащая пары имя / значение, разделенные & :

HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

Мы можем обернуть переменные формы в LinkedMultiValueMap :

MultiValueMap map= new LinkedMultiValueMap(); map.add("id", "1");

Затем мы создаем запрос, используя экземпляр HttpEntity :

HttpEntity
    
      request = new HttpEntity(map, headers);
    

Наконец, мы можем подключиться к службе REST, вызвав restTemplate.postForEntity () в конечной точке : / foos / form

ResponseEntity response = restTemplate.postForEntity( fooResourceUrl+"/form", request , String.class); assertThat(response.getStatusCode(), is(HttpStatus.CREATED));

6. Используйте OPTIONS для получения разрешенных операций

Далее мы кратко рассмотрим использование запроса OPTIONS и изучим разрешенные операции с определенным URI с использованием этого типа запроса; API - это optionsForAllow :

Set optionsForAllow = restTemplate.optionsForAllow(fooResourceUrl); HttpMethod[] supportedMethods = {HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE}; assertTrue(optionsForAllow.containsAll(Arrays.asList(supportedMethods)));

7. Используйте PUT для обновления ресурса.

Next, we'll start looking at PUT and more specifically the exchange() API for this operation, since the template.put API is pretty straightforward.

7.1. Simple PUT With exchange()

We'll start with a simple PUT operation against the API — and keep in mind that the operation isn't returning a body back to the client:

Foo updatedInstance = new Foo("newName"); updatedInstance.setId(createResponse.getBody().getId()); String resourceUrl = fooResourceUrl + '/' + createResponse.getBody().getId(); HttpEntity requestUpdate = new HttpEntity(updatedInstance, headers); template.exchange(resourceUrl, HttpMethod.PUT, requestUpdate, Void.class);

7.2. PUT With exchange() and a Request Callback

Next, we're going to be using a request callback to issue a PUT.

Let's make sure we prepare the callback, where we can set all the headers we need as well as a request body:

RequestCallback requestCallback(final Foo updatedInstance) { return clientHttpRequest -> { ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(clientHttpRequest.getBody(), updatedInstance); clientHttpRequest.getHeaders().add( HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); clientHttpRequest.getHeaders().add( HttpHeaders.AUTHORIZATION, "Basic " + getBase64EncodedLogPass()); }; }

Next, we create the Resource with a POST request:

ResponseEntity response = restTemplate .exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class); assertThat(response.getStatusCode(), is(HttpStatus.CREATED));

And then we update the Resource:

Foo updatedInstance = new Foo("newName"); updatedInstance.setId(response.getBody().getId()); String resourceUrl =fooResourceUrl + '/' + response.getBody().getId(); restTemplate.execute( resourceUrl, HttpMethod.PUT, requestCallback(updatedInstance), clientHttpResponse -> null);

8. Use DELETE to Remove a Resource

Чтобы удалить существующий ресурс, мы быстро воспользуемся API delete () :

String entityUrl = fooResourceUrl + "/" + existingResource.getId(); restTemplate.delete(entityUrl); 

9. Настроить тайм-аут

Мы можем настроить RestTemplate на тайм-аут, просто используя ClientHttpRequestFactory :

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory()); private ClientHttpRequestFactory getClientHttpRequestFactory() { int timeout = 5000; HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); clientHttpRequestFactory.setConnectTimeout(timeout); return clientHttpRequestFactory; }

И мы можем использовать HttpClient для дальнейших параметров конфигурации:

private ClientHttpRequestFactory getClientHttpRequestFactory() { int timeout = 5000; RequestConfig config = RequestConfig.custom() .setConnectTimeout(timeout) .setConnectionRequestTimeout(timeout) .setSocketTimeout(timeout) .build(); CloseableHttpClient client = HttpClientBuilder .create() .setDefaultRequestConfig(config) .build(); return new HttpComponentsClientHttpRequestFactory(client); }

10. Заключение

В этой статье мы рассмотрели основные HTTP-глаголы, используя RestTemplate для оркестровки запросов с их использованием.

Если вы хотите разобраться, как выполнить аутентификацию с помощью шаблона, ознакомьтесь с нашей статьей о базовой аутентификации с помощью RestTemplate.

Реализацию всех этих примеров и фрагментов кода можно найти на GitHub.