Главная » Spring » Преобразование HTTP-сообщений Spring

0

Как было показано в главе 8 и в предыдущем разделе, типичный метод контроллера Spring MVC завершается записью некоторых данных в модель и определением логического имени представления для отображения этих данных. Несмотря на большое разнообразие способов заполнения модели данными и идентификации представ- лений, все методы-обработчики контроллеров, встречавшиеся нам до сих пор, следовали этому основному шаблону.

Но когда задача контроллера состоит в том, чтобы воспроизвести ресурс в некотором формате, существует более прямой путь к цели, минуя модели и представления. При таком подходе к реализации метода-обработчика возвращаемый им объект автоматически преоб- разуется в формат, запрошенный клиентом.

Использование этого нового приема начинается с применения ан- нотации @ResponseBody к методу-обработчику контроллера.

Возврат ресурса в теле ответа

Обычно, когда метод-обработчик возвращает Java-объект (любого типа, отличного от String), этот объект помещается в модель для

последующего отображения в представлении. Но если метод отме- тить аннотацией @ResponseBody, тогда возвращаемый им объект будет передан механизму преобразования HTTP-сообщений и превращен в формат, требуемый клиентом.

Например, рассмотрим следующий метод getSpitter()  класса

SpitterController:

@RequestMapping(value  =  "/{username}",  method  =  RequestMethod.GET, headers     =     {"Accept=text/xml,     application/json"})

public  @ResponseBody

Spitter getSpitter(@PathVariable String username) { return   spitterService.getSpitter(username);

}

Аннотация @ResponseBody сообщает фреймворку Spring, что возвра- щаемый объект следует отправить клиенту как ресурс, преобразо- вав его в некоторый формат, доступный для клиента. Точнее, ресурс должен быть преобразован в формат в соответствии с содержимым заголовка Accept. Если в запросе отсутствует заголовок Accept, тогда предполагается, что клиент способен принимать ресурсы в любом формате.

Что касается заголовка Accept, обратите внимание на аннотацию

@RequestMapping перед методом getSpitter(). Атрибут headers указыва- ет, что этот метод будет обрабатывать только запросы, в которых заголовок Accept включает text/xml или application/json. Любые дру- гие запросы, даже если это будут GET-запросы, в которых URL со- ответствует указанному шаблону, не будут обрабатываться данным методом. Они либо будут обработаны другим методом (если имеется соответствующий метод), либо клиенту будет отправлен ответ с ко- дом состояния HTTP 406 (Not Acceptable).

Преобразование произвольных Java-объектов, возвращаемых ме- тодами обработчиками, в представление, доступное для клиента, вы- полняется одним из преобразователей HTTP-сообщений, входящих в состав Spring и перечисленных в табл. 12.2.

Например, допустим, что в заголовке Accept запроса клиент сооб- щил, что он способен принимать данные в формате application/json. Допустим также, что в библиотеке классов приложения присутству- ет библиотека Jackson JSON. В этом случае объект, возвращаемый методом-обработчиком, можно передать преобразователю MappingJac ksonHttpMessageConverter для преобразования его в формат JSON перед передачей клиенту. С другой стороны, если заголовок в запросе ука-

Таблица 12.2. Фреймворк Spring предоставляет несколько преоб- разователей HTTP-сообщений, способных преобразовывать дан- ные различных Java-типов в представления ресурсов и обратно

Преобразователь

Назначение

AtomFeedHttpMessageConverter

Преобразует объекты класса Feed из библиотеки Rome1 в ленту Atom и обратно (тип application/atom+xml). Регистрирует- ся, если библиотека Rome присутствует

в библиотеке классов

BufferedImageHttpMessageConverter

Преобразует BufferedImages в двоичные изображения и обратно

ByteArrayHttpMessageConverter

Читает/записывает массивы байт. Читает содержимое всех типов (*/*) и записывает как содержимое типа application/octet- stream. Регистрируется по умолчанию

FormHttpMessageConverter

Преобразует содержимое типа

application/x-www-form-urlencoded

в объект MultiValueMap<String,  String>, а также преобразует объекты типа

MultiValueMap<String,  String> в содержи-

мое application/x-www-form-urlencoded

и MultiValueMap<String,  Object> в multipart/ form-data

Jaxb2RootElementHttpMessageConverter

Преобразует данные из формата XML (text/xml  или application/xml) в JAXB2- объекты и обратно. Регистрируется, если библиотека JAXB v2 присутствует в библиотеке классов

MappingJacksonHttpMessageConverter

Преобразует данные из формата JSON в типизированные объекты или нетипи- зированные объекты HashMap и обратно.

Регистрируется, если библиотека Jackson JSON присутствует в библиотеке классов

MarshallingHttpMessageConverter

Преобразует данные из формата XML и обратно с использованием внедряемых компонентов преобразования. В число поддерживаемых входят компоненты из библиотек Castor, JAXB2, JIBX, XMLBeans и XStream

ResourceHttpMessageConverter

Преобразует объекты типа Resource. Регистрируется по умолчанию

1   https://rome.dev.java.net.

Таблица 12.2 (окончание)

RssChannelHttpMessageConverter

Преобразует объекты класса Channel

из библиотеки Rome в ленту RSS и об- ратно. Регистрируется, если библиотека Rome присутствует в библиотеке классов

SourceHttpMessageConverter

Преобразует данные из формата XML в  объекты  javax.xml.transform.Source

и обратно. Регистрируется по умолчанию

StringHttpMessageConverter

Преобразует содержимое всех типов (*/*) в объекты String. Преобразует объекты Strings в содержимое типа text/plain. Регистрируется по умолчанию

XmlAwareFormHttpMessageConverter

Расширение преобразователя FormHttpMessageConverter,  добавляет поддержку преобразования фрагмен- тов в формате XML с использованием SourceHttpMessageConverter. Регистрирует- ся по умолчанию

зывает, что клиент предпочитает формат text/xml, преобразование данных в формат XML можно поручить преобразователю Jaxb2Root ElementHttpMessageConverter.

Обратите внимание, что преобразователи HTTP-сообщений из табл. 12.2 (кроме трех) регистрируются по умолчанию, поэтому их не требуется настраивать отдельно. Однако для их поддержки может понадобиться добавить дополнительные библиотеки в библиотеку классов приложения (classpath). Например, для преобразования данных в формат JSON и обратно с помощью преобразователя Mapp ingJacksonHttpMessageConverter необходимо будет добавить библиотеку Jackson JSON Processor1.

Прием ресурса в теле запроса

Другому участнику диалога в стиле RESTful, клиенту, может по- требоваться отправить на сервер объект в формате JSON, XML или каком-то другом. Было бы неудобно получать эти объекты в исход- ном виде в методе контроллера и пытаться преобразовать их вруч- ную. К счастью, аннотация @RequestBody позволяет выполнить все необходимые преобразования объектов, отправленных клиентом, как это делает аннотация @ResponseBody с объектами, возвращаемы- ми клиентам.

1   http://jackson.codehaus.org.

Допустим, что клиент отправил запрос PUT с данными для объекта Spitter в формате JSON. Чтобы принять это сообщение как объект Spitter, достаточно всего лишь отметить соответствующий параметр типа Spitter метода-обработчика аннотацией @RequestBody:

@RequestMapping(value  =  "/{username}",  method  =  RequestMethod.PUT, headers     =     "Content-Type=application/json")

@ResponseStatus(HttpStatus.NO_CONTENT)

public void updateSpitter(@PathVariable String username,

@RequestBody Spitter spitter) { spitterService.saveSpitter(spitter);

}

Получив запрос, фреймворк Spring MVC определит, что этот запрос должен обрабатывать метод updateSpitter(). Но полученное сообщение имеет формат JSON, а метод ожидает получить объект Spitter. В этом случае для преобразования сообщения из формата JSON в объект Spitter можно было бы задействовать преобразова- тель MappingJacksonHttpMessageConverter. Чтобы этот выбор состоялся, должны быть выполнены следующие условия:

# заголовок Content-Type запроса должен иметь значение appli-

cation/json;

# библиотека Jackson JSON должна находиться в библиотеке классов приложения.

Возможно, вы обратили внимание, что метод updateSpitter() также отмечен аннотацией @ResponseStatus. После обработки запроса PUT не требуется возвращать клиенту какие-либо данные, а аннотирование метода updateSpitter() таким способом обеспечивает отправку кли- енту кода состояния HTTP 204 (No Content).

К настоящему моменту у нас имеются несколько контроллеров Spring MVC с методами-обработчиками для обработки запросов на получение ресурсов. Нам предстоит обсудить еще ряд тем, касаю- щихся определения RESTful API с помощью Spring MVC, и мы вер- немся к этому обсуждению в разделе 12.5. Но перед этим немного отвлечемся и посмотрим, как можно использовать класс RestTemplate для создания клиентов, потребляющих ресурсы.

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

По теме:

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