Перейти к основному содержимому

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

· 5 мин. чтения

Задача: Наибольшая подстрока без повторений

Для заданной строки s, найдите длину наибольшей подстроки без повторяющихся символов. Подстрока — это непрерывная непустая последовательность символов внутри строки...

ANDROMEDA 42

1. Обзор

В этом руководстве мы собираемся проиллюстрировать широкий спектр операций, в которых можно использовать клиент Spring REST — 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
= "http://localhost:8080/spring-rest/foos";
ResponseEntity<String> response
= restTemplate.getForEntity(fooResourceUrl + "/1", String.class);
Assertions.assertEquals(response.getStatusCode(), HttpStatus.OK);

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

ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(response.getBody());
JsonNode name = root.path("name");
Assertions.assertNotNull(name.asText());

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

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

Мы также можем напрямую сопоставить ответ с 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);
Assertions.assertNotNull(foo.getName());
Assertions.assertEquals(foo.getId(), 1L);

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

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

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

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

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

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

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

5.1. API postForObject( ) ``

RestTemplate restTemplate = new RestTemplate();

HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class);
Assertions.assertNotNull(foo);
Assertions.assertEquals(foo.getName(), "bar");

5.2. API postForLocation( )

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

HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
URI location = restTemplate
.postForLocation(fooResourceUrl, request);
Assertions.assertNotNull(location);

5.3. API обмена( ) ``

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

RestTemplate restTemplate = new RestTemplate();
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
ResponseEntity<Foo> response = restTemplate
.exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);

Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);

Foo foo = response.getBody();

Assertions.assertNotNull(foo);
Assertions.assertEquals(foo.getName(), "bar");

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

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

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

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

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

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

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

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

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

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

ResponseEntity<String> response = restTemplate.postForEntity(
fooResourceUrl+"/form", request , String.class);
Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);

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

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

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

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

Далее мы начнем рассматривать PUT и, более конкретно, API exchange() для этой операции, поскольку API template.put довольно прост.

7.1. Простой PUT с обменом()

Мы начнем с простой операции PUT для API — и имейте в виду, что операция не возвращает тело клиенту:

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

7.2. PUT с exchange() и обратным вызовом запроса

Далее мы собираемся использовать обратный вызов запроса для отправки PUT.

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

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

Далее мы создаем ресурс с помощью POST-запроса:

ResponseEntity<Foo> response = restTemplate
.exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);
Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);

И затем мы обновляем Ресурс:

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. Используйте DELETE для удаления ресурса

Чтобы удалить существующий ресурс, мы быстро воспользуемся 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 .