Главная » Spring » Чтение ресурсов Spring

0

Вы могли заметить, что в табл. 12.3 перечислены два метода, вы- полняющих GET-запросы: getForObject() и getForEntity(). Как отмеча- лось выше, каждый из этих методов имеет три перегруженные вер- сии. Ниже приводятся сигнатуры трех версий метода getForObject():

<T>  T  getForObject(URI  url,  Class<T>  responseType)

throws RestClientException;

<T>  T  getForObject(String  url,  Class<T>  responseType,

Object… uriVariables) throws RestClientException;

<T>  T  getForObject(String  url,  Class<T>  responseType,

Map<String,   ?>   uriVariables)   throws   RestClientException;

И сигнатуры трех версий метода getForEntity():

<T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws    RestClientException;

<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object…  uriVariables)  throws  RestClientException;

<T>  ResponseEntity<T>  getForEntity(String  url,  Class<T>  responseType, Map<String,   ?>   uriVariables)   throws   RestClientException;

За исключением типа возвращаемого значения, методы getFor- Object() являются  зеркальным  отражением  методов  getForEntity(). И в действительности они действуют точно так же. Оба метода вы- полняют GET-запрос, чтобы извлечь ресурс с указанным URL. И оба отображают этот ресурс в объект некоторого типа, определяемого

параметром responseType. Единственное отличие состоит в том, что метод  getForObject()  просто  возвращает  объект  требуемого  типа, а метод getForEntity() возвращает этот объект наряду с дополнитель- ной информацией об ответе.

Рассмотрим сначала более простой метод getForObject(). Затем узнаем, как получить дополнительную информацию из ответа на GET-запрос с помощью метода getForEntity().

Извлечение ресурсов

Метод getForObject() является сугубо прагматичным способом из- влечения ресурсов. С его помощью программа запрашивает ресурс и получает его в форме объекта указанного типа. В качестве простого примера использования метода getForObject() рассмотрим еще одну версию  метода  retrieveSpittlesForSpitter():

public   Spittle[]   retrieveSpittlesForSpitter(String   username)   { return new RestTemplate().getForObject(

"http://localhost:8080/Spitter/spitters/{spitter}/spittles", Spittle[].class,  username);

}

Сравните его с листингом 12.5, где реализация retrieveSpittles- ForSpitter() содержит более десятка строк кода. Применение класса RestTemplate позволило сократить метод до нескольких строк (и строк было бы еще меньше, если бы их не нужно было переносить, чтобы уместить по ширине книжной страницы).

Новая версия метода retrieveSpittlesForSpitter() начинается с соз- дания экземпляра RestTemplate (при желании можно было бы исполь- зовать внедренный экземпляр), а затем вызывается метод getFor- Object(), чтобы извлечь список сообщений. То есть запрашивается массив объектов Spittle. После получения массива он возвращается вызывающей программе.

Обратите внимание, что для конструирования URL в этой новой версии метода retrieveSpittlesForSpitter() не  используется  опера- ция конкатенации строк. Вместо этого используется тот факт, что RestTemplate принимает параметризованные адреса URL. Переменная- заполнитель {spitter} в URL будет замещена значением параметра username метода. Последний аргумент метода getForObject() – это спи- сок аргументов переменной длины, где каждый аргумент замещает переменные-заполнители в URL в порядке их следования.

При желании можно было бы поместить параметр username в ото- бражение Map с ключом spitter и передать это отображение методу getForObject() в последнем параметре:

public   Spittle[]   retrieveSpittlesForSpitter(String   username)   { Map<String, String> urlVariables = new HashMap<String, String(); urlVariables.put("spitter",      username);

return new RestTemplate().getForObject( "http://localhost:8080/Spitter/spitters/{spitter}/spittles", Spittle[].class,      urlVariables);

}

Здесь отсутствует  явное  преобразование  данных  в формате JSON в объект. Преобразование тела ответа в требуемый объект выполняется методом getForObject() автоматически. Это преобра- зование выполняется с привлечением все тех же преобразовате- лей HTTP-сообщений, перечисленных в табл. 12.2, которые Spring MVC использует в методах-обработчиках, отмеченных аннотацией

@ResponseBody.

В этом методе также отсутствует обработка исключений. И вовсе не потому, что метод getForObject() не может возбуждать исключе- ния, а потому, что любые исключения, возбуждаемые им, являются неконтролируемыми. Если в методе getForObject() что-то пойдет не так, он возбудит неконтролируемое исключение RestClientException. При желании его можно перехватить, но компилятор не вынуждает делать это.

Извлечение метаданных из ответа

В качестве альтернативы методу getForObject() класс RestTemplate предлагает метод getForEntity(). Этот метод действует практиче- ски так же, как метод getForObject(). Но если метод getForObject() возвращает только ресурс (преобразованный в Java-объект с по- мощью преобразователя HTTP-сообщений), то метод getForEntity() возвращает тот же самый объект, помещенный внутрь объекта ResponseEntity. Объект ResponseEntity несет в себе также дополни- тельную информацию об ответе, такую как код состояния HTTP и заголовки ответа.

Объект ResponseEntity можно использовать, чтобы извлечь значе- ние какого-либо заголовка ответа. Например, представьте, что поми- мо ресурса необходимо также определить, когда ресурс изменялся в последний раз. Допустим, что сервер предоставляет такую инфор-

мацию в заголовке Last-Modified. Тогда, чтобы получить требуемую информацию, можно воспользоваться методом getHeaders(), как по- казано ниже:

Date     lastModified     =     new     Date(response.getHeaders().getLastModified());

Метод getHeaders() возвращает объект HttpHeaders, имеющий не- сколько вспомогательных методов для извлечения заголовков, включая метод getLastModified(), возвращающий количество милли- секунд, прошедших с 1 января 1970 года.

Кроме метода getLastModified(), класс HttpHeaders содержит сле- дующие методы:

public List<MediaType> getAccept() { … } public  List<Charset>  getAcceptCharset()  {  … } public Set<HttpMethod> getAllow() { … } public  String  getCacheControl()  {  … }

public  long  getContentLength()  {  … } public MediaType getContentType() { … } public  long  getDate()  {  … }

public String getETag() { … } public long getExpires() { … }

public long getIfNotModifiedSince() { … } public List<String> getIfNoneMatch() { … } public long getLastModified() { … }

public  URI  getLocation()  {  … } public  String  getPragma()  {  … }

Более универсальный способ доступа к HTTP-заголовкам обес- печивают методы get() и getFirst(). Оба принимают строковый ар- гумент, определяющий имя заголовка. Метод get() возвращает спи- сок строковых значений – по одному для каждого заголовка. Метод getFirst() возвращает значение только первого заголовка.

Чтобы получить код состояния HTTP, можно воспользоваться ме- тодом getStatusCode(). Например, взгляните на реализацию метода retrieveSpittlesForSpitter()   в  листинге  12.6.

Листинг 12.6. Объект ResponseEntity включает код состояния HTTP

public   Spittle[]   retrieveSpittlesForSpitter(String   username)   { ResponseEntity<Spittle[]> response = new RestTemplate().getForEntity(

"http://localhost:8080/Spitter/spitters/{spitter}/spittles", Spittle[].class,  username);

if(response.getStatusCode()   ==   HttpStatus.NOT_MODIFIED)   { throw   new   NotModifiedException();

}

return response.getBody();

}

Если сервер вернет код состояния HTTP 304, это будет свидетель- ствовать о том, что содержимое на сервере не изменялось с момента последнего обращения клиента. В этом случае метод возбудит ис- ключение NotModifiedException, чтобы сообщить, что клиент должен извлечь данные из своего кеша.

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

По теме:

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