Посібник з RestTemplate

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 = "//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());

Тут ми працюємо з тілом відповіді як стандартним рядком і використовуємо Джексона (та структуру вузла JSON, яку надає Джексон) для перевірки деяких деталей.

3.2. Отримання POJO замість JSON

Ми також можемо зіставити відповідь безпосередньо з DTO Resource:

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 ,

Подібним чином, давайте подивимось на операцію, яка замість повернення повного Ресурсу просто повертає Розташування цього новоствореного Ресурсу:

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 є опціямиForAllow :

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 для організації запитів, використовуючи всі ці.

Якщо ви хочете дізнатись, як зробити автентифікацію за допомогою шаблону, перегляньте нашу статтю про Basic Auth with RestTemplate.

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