Главная » Spring » Обмен ресурсами Spring

0

К настоящему моменту мы познакомились со всеми основными методами класса RestTemplate, которые используются для получения, изменения, удаления и создания новых ресурсов. Наряду с ними мы рассмотрели также два специальных метода, getForEntity() и postForEntity(), возвращающие ресурс, обернутый объектом Request- Entity, из которого можно извлечь код состояния HTTP и заголовки ответа.

Возможность чтения заголовков ответа весьма полезна на практи- ке. Но что, если приложению потребуется отправлять на сервер заго- ловки запроса? Для этой цели можно использовать метод exchange().

Подобно остальным методам класса RestTemplate, метод exchange()

имеет три перегруженные версии со следующими сигнатурами:

<T> ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?>  requestEntity,  Class<T>  responseType) throws    RestClientException;

<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object…   uriVariables)   throws   RestClientException;

<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?>   requestEntity,   Class<T>   responseType, Map<String,   ?>   uriVariables)   throws   RestClientException;

Как видите, сигнатуры трех перегруженных версий метода exchange() соответствуют шаблону, общему для всех методов класса RestTemplate. Первая версия принимает объект java.net.URI, иденти- фицирующий целевой URL, а остальные две принимают URL в виде строки и аргументы со значениями для переменных-заполнителей в URL.

Метод exchange() принимает также параметр HttpMethod, который определяет, какой метод HTTP должен использоваться. В зависимо- сти от значения этого параметра метод exchange() может выполнять те же операции, что и любые другие методы класса RestTemplate.

Например, как показано ниже, извлечь ресурс Spitter можно с по- мощью метода getForEntity():

ResponseEntity<Spitter> response = rest.getForEntity( "http://localhost:8080/Spitter/spitters/{spitter}", Spitter.class,       spitterId);

Spitter  spitter  =  response.getBody();

А также с помощью метода exchange():

ResponseEntity<Spitter> response = rest.exchange( "http://localhost:8080/Spitter/spitters/{spitter}", HttpMethod.GET,   null,  Spitter.class,  spitterId);

Spitter  spitter  =  response.getBody();

В этом примере, передав значение HttpMethod.GET в качестве мето- да HTTP, приложение предлагает методу exchange() отправить GET- запрос. Третий аргумент предназначен для отправляемого ресурса, но, поскольку в данном случае выполняется запрос GET, в нем пере- дается пустая ссылка (null). Следующий аргумент определяет ожи- даемый тип возвращаемого объекта. И последний аргумент – это значение, которое будет подставлено на место переменной-заполни- теля {spitter}  в указанном шаблоне URL.

При таком использовании метод exchange() практически иден- тичен методу getForEntity(). Но, в отличие от getForEntity() или getForObject(), метод exchange() позволяет устанавливать заголовки в запросе. Вместо значения null методу exchange() можно передать объект HttpEntity с требуемыми заголовками.

Если приложение не определяет заголовки, метод exchange() от- правит GET-запрос на получение ресурса Spitter со следующими за- головками:

GET    /Spitter/spitters/habuma    HTTP/1.1

Accept:   application/xml,   text/xml,   application/*+xml,   application/json Content-Length: 0

User-Agent: Java/1.6.0_20 Host:  localhost:8080 Connection:  keep-alive

Обратите внимание на заголовок Accept. Он сообщает серверу, что приложение способно принимать содержимое в нескольких фор- матах XML, а также в формате application/json. Это дает серверу большую свободу выбора при определении формата представления возвращаемого ресурса. Предположим, что необходимо ограничить сервер форматом JSON. В этом случае следует оставить в заголовке Accept   только значение application/json.

Установка заголовков запроса сводится к созданию объекта HttpEntity, содержащего объект MultiValueMap с требуемыми заголов- ками:

MultiValueMap<String,   String>   headers   =

new  LinkedMultiValueMap<String,  String>(); headers.add("Accept",     "application/json");

HttpEntity<Object>  requestEntity   =  new   HttpEntity<Object>(headers);

Здесь создается объект LinkedMultiValueMap и в него добавляется за- головок Accept со значением application/json. Затем создается объект

HttpEntity (с обобщенным типом Object) вызовом конструктора, кото- рому передается аргумент с объектом MultiValueMap. Если бы это был запрос PUT или POST, точно так же можно было бы добавить в объект HttpEntity  тело запроса – для запроса GET  в этом нет необходимости.

Теперь  можно  вызвать  метод  exchange(),  передав  ему  объект

HttpEntity:

ResponseEntity<Spitter> response = rest.exchange( "http://localhost:8080/Spitter/spitters/{spitter}", HttpMethod.GET,   requestEntity,  Spitter.class,  spitterId);

Spitter  spitter  =  response.getBody();

На первый взгляд кажется, что результат будет тот же самый. Приложение должно получить запрошенный объект Spitter. Но в действительности на сервер будет отправлен запрос со следующими заголовками:

GET   /Spitter/spitters/habuma  HTTP/1.1 Accept:     application/json

Content-Length:  0

User-Agent: Java/1.6.0_20 Host:  localhost:8080 Connection:  keep-alive

И если сервер способен преобразовать объект Spitter в формат JSON, тело ответа должно быть представлено в формате JSON.

В этом разделе было показано, как пользоваться различными ме- тодами класса RestTemplate и как с их помощью приложения-клиен- ты, написанные на языке Java, могут взаимодействовать с ресурсами RESTful на сервере. Но что, если клиентом является веб-браузер? Когда доступ к ресурсам REST осуществляется с помощью брау- зера, необходимо учитывать некоторые ограничения, особенно это касается диапазона методов HTTP, поддерживаемых браузером. В завершение этой главы посмотрим, как фреймворк Spring помо- гает преодолевать данные ограничения.

Источник:   Уоллс К., Spring в действии. – М.: ДМК Пресс, 2013. – 752 с.: ил.

По теме:

  • Комментарии