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 .