Как работает аннотация Spring @ResponseBody в этом примере приложения RESTful?

у меня есть метод, который аннотируется следующим образом:

/**
* Provide a list of all accounts.
*/
//  TODO 02: Complete this method.  Add annotations to respond
//  to GET /accounts and return a List<Account> to be converted.
//  Save your work and restart the server.  You should get JSON results when accessing 
//  http://localhost:8080/rest-ws/app/accounts
@RequestMapping(value="/orders", method=RequestMethod.GET)
public @ResponseBody List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

поэтому я знаю, что по этой аннотации:

@RequestMapping(value="/orders", method=RequestMethod.GET)

этот метод handle GET HTTP-запросы к ресурсу, представленному URL /приказ.

этот метод вызывает объект DAO, который возвращает список.

здесь счета представляющий пользователя в системе и имеет некоторые поля, которые представляют этот пользователь, что-то типа:

public class Account {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long entityId;

    @Column(name = "NUMBER")
    private String number;

    @Column(name = "NAME")
    private String name;

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name = "ACCOUNT_ID")
    private Set<Beneficiary> beneficiaries = new HashSet<Beneficiary>();

    ...............................
    ...............................
    ...............................
}

мой вопрос: как именно это делает @ResponseBody работа с аннотациями?

он расположен перед возвращено List<Account> объект, так что я думаю, что он относится к этому списку. В документации курса указано, что эта аннотация выполняет функцию:

убедитесь, что результат будет записан в HTTP-ответ HTTP Конвертер сообщений (вместо MVC Вид.)

а также чтение официальной весенней документации: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ResponseBody.html

кажется, что он принимает List<Account> объект и помещает его в Http Response. Это правильно или я неправильно понял?

написано в комментарии предыдущего accountSummary() способ есть:

вы должны получить JSON результаты при доступе http://localhost:8080/rest-ws/app/accounts

так что именно это означает? Означает ли это, что и Http Response? Или что?

если это утверждение истинно, где указано, что объект будет автоматически преобразован в ? Является ли стандартный формат принят, когда @ResponseBody аннотация используется или указывается в другом месте?

4 ответов


прежде всего, аннотация не аннотирует List. Он аннотирует метод, так же как RequestMapping делает. Ваш код эквивалентен

@RequestMapping(value="/orders", method=RequestMethod.GET)
@ResponseBody
public List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

теперь аннотация означает, что возвращаемое значение метода будет составлять тело HTTP-ответа. Конечно, HTTP-ответ не может содержать объекты Java. Таким образом, этот список учетных записей преобразуется в формат, подходящий для приложений REST, обычно JSON или XML.

выбор формата зависит от установленных преобразователей сообщений, от значений produces атрибут аннотации RequestMapping и типа контента, который принимает клиент (который доступен в заголовках HTTP-запросов). Например, если запрос говорит, что он принимает XML, но не JSON, и установлен конвертер сообщений, который может преобразовать список в XML, то XML будет возвращен.


первое, что нужно понять, - это разница в архитектуре.

на одном конце у вас есть архитектура MVC, которая основана на вашем обычном веб-приложении, используя веб-страницы, и браузер делает запрос на страницу:

Browser <---> Controller <---> Model
               |      |
               +-View-+

браузер делает запрос, контроллер (@Controller) получает модель (@Entity) и создает представление (JSP) из модели, и представление возвращается обратно клиенту. Это базовая архитектура веб-приложений.

On с другой стороны, у вас спокойная архитектура. В этом случае нет никакого представления. Контроллер только отправляет обратно модель (или представление ресурса, в более спокойных терминах). Клиент может быть приложением JavaScript, серверным приложением Java, любым приложением, в котором мы предоставляем API REST. С помощью этой архитектуры клиент решает, что делать с этой моделью. Возьмем, к примеру, Twitter. Twitter Как web (REST) API, который позволяет нашим приложениям использовать его API для получения таких вещей, как статус обновления, чтобы мы могли использовать его для размещения этих данных в нашем приложении. Эти данные будут представлены в каком-то формате, например JSON.

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

но когда мы используем @ResponseBody, мы говорим, что мы не хотим смотреть производства. Мы просто хотим отправить возвращаемый объект как тело, в любом формате, который мы указываем. Мы не хотели бы, чтобы это был сериализованный объект Java (хотя это возможно). Так что да, он должен быть преобразован в какой-то другой общий тип (Этот тип обычно рассматривается через согласование контента-см. ссылку ниже.) Честно говоря, я мало работаю с весной, хотя и балуюсь ею там и сям. Обычно я использую

@RequestMapping(..., produces = MediaType.APPLICATION_JSON_VALUE)

чтобы установить тип контента, но, возможно, JSON является значением по умолчанию. Не цитируйте меня, но если вы получаете JSON, и вы не указали produces, тогда, возможно, это значение по умолчанию. JSON-не единственный формат. Например, вышеизложенное может быть легко отправлено в XML, но вам нужно будет иметь produces до MediaType.APPLICATION_XML_VALUE и я считаю, что вам нужно настроить HttpMessageConverter для JAXB. Что касается JSON MappingJacksonHttpMessageConverter настроен, когда у нас есть Джексон в classpath.

Я бы взял некоторое время, чтобы узнать о Содержание Переговоров. Это очень важная часть отдыха. Это поможет вам узнать о различных форматах ответов и о том, как сопоставить их с вашими методами.


как упоминал JB Низет,

@RequestMapping(value="/orders", method=RequestMethod.GET)
@ResponseBody
public List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

и

@RequestMapping(value="/orders", method=RequestMethod.GET)
public @ResponseBody List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

одинаковы. как @ResponseBody аннотации метод не список. @GMsoF-установленные конвертеры сообщений здесь можно использовать следующим образом.

@RequestMapping(value="/orders", method=RequestMethod.GET , produces={"application/json","application/xml"})
@ResponseBody
public List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

спасибо :)


далее к этому, тип возврата определяется

  1. что HTTP-запрос говорит, что он хочет - в его заголовке Accept. Попробуйте посмотреть на начальный запрос, как посмотреть, что Accept установлен.

  2. какие настройки весны HttpMessageConverters. Spring MVC настроит конвертеры для XML (используя JAXB) и JSON, если библиотеки Джексона находятся на пути к классам.

Если есть выбор, он выбирает один - в этом примере это оказывается, это JSON.

этой is в ходе заметки. Ищите заметки о конвертерах сообщений и согласовании контента.