Spring @ResponseBody注释如何工作?


89

我有一种通过以下方式注释的方法:

/**
* 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)

此方法处理对由URL / orders表示的资源发出的GET HTTP请求。

此方法调用返回List的DAO对象。

其中Account代表系统上的用户,并具有代表该用户的某些字段,例如:

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>对象之前,因此我认为它引用此List。课程文档指出,此注释可起到以下作用:

确保结果将通过HTTP消息转换器(而不是MVC视图)写入到HTTP响应中。

还要阅读Spring的官方文档:http : //docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ResponseBody.html

似乎它带了List<Account>物体并将它放入了Http Response。这是正确的还是我误会了?

写入前accountSummary()一种方法的注释中有:

访问http:// localhost:8080 / rest-ws / app / accounts时,您应该获得JSON结果

那么这到底是什么意思呢?这是否意味着List<Account>accountSummary()方法返回的对象会自动转换为JSON格式,然后放入Http Response?中?或者是什么?

如果此声明为true,则在哪里指定对象将自动转换为JSON格式?@ResponseBody使用注释时是采用标准格式还是在其他地方指定?

Answers:


160

首先,注释不进行注释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。


3
嗨,我们如何设置“已安装的消息转换器”?我希望默认值始终转换为Json。我能做到吗?
GMsoF

@JB Nizet您能解释一下为什么HTTP响应不能包含Java对象吗?我是Java的新手。
Naved Ali

3
@ Er.NavedAli阅读了http规范,http响应内容类型定义了http响应可以包含的合法内容。合法值可以是“ application / octet-stream”,“ image / jpeg”,“ text / HTML”,但是java对象不是合法值。
赵刚

@ZhaoGang,在我的测试案例中,内容类型“ application / json”已替换为“ application / xml”,但响应主体似乎没有变化,仍然使用json格式。
LeafiWan

1
确切地说,我的意思是在哪个春季课程中做出决定如何返回响应的决定?你能指出我在github上的源代码吗?如果客户端接受XML但未安装XML转换器,还会发生什么?
anir

63

首先要了解的基础是架构上的差异。

一端具有MVC架构,该架构基于使用网页的常规Web应用程序,并且浏览器发出对页面的请求:

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

浏览器发出请求,控制器(@Controller)获取模型(@Entity),然后从模型创建视图(JSP),然后将视图返回给客户端。这是基本的Web应用程序体系结构。

另一方面,您具有RESTful架构。在这种情况下,没有视图。Controller仅发回模型(或使用更RESTful的术语表示资源表示)。客户端可以是JavaScript应用程序,Java服务器应用程序,也可以是我们将REST API暴露于其中的任何应用程序。利用这种架构,客户可以决定如何处理该模型。以Twitter为例。Twitter作为Web(REST)API,允许我们的应用程序使用其API来获取状态更新之类的信息,以便我们可以使用它将数据放入我们的应用程序中。这些数据将以JSON之类的格式出现。

话虽这么说,当与Spring MVC一起使用时,它最初是为处理基本的Web应用程序体系结构而构建的。可能有不同的方法签名风格,可以从我们的方法中生成视图。该方法可以返回ModelAndView我们在其中显式创建它的位置,也可以通过隐式方法返回一些被设置为模型属性的任意对象。但是无论哪种方式,在请求-响应周期的某个地方,都会产生一个视图。

但是,当我们使用时@ResponseBody,是说我们不希望产生视图。我们只想以指定的任何格式将返回对象作为正文发送。我们不希望它成为序列化的Java对象(尽管可能)。因此,是的,需要将其转换为其他一些常见类型(此类型通常通过内容协商来处理-请参见下面的链接)。老实说,尽管我在这里和那里涉猎,但我对Spring的工作并不多。通常我用

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

设置内容类型,但是默认情况下可能是JSON。不要引用我,但是如果您正在获取JSON,并且尚未指定produces,则可能是默认设置。JSON不是唯一的格式。例如,以上内容可以轻松地以XML格式发送,但是您需要具有producesto MediaType.APPLICATION_XML_VALUE,我相信您需要HttpMessageConverter为JAXB 配置the 。至于MappingJacksonHttpMessageConverter配置的JSON ,当我们在类路径上有Jackson时。

我将花一些时间来学习内容协商。这是REST的重要组成部分。它可以帮助您了解不同的响应格式以及如何将它们映射到您的方法。


如果在调查如何创建通用/动态REST控制器而不使用时找到了答案@Controller/@RestController。我发现,我需要以某种方式省略视图解析器层。这不是那么简单,因为AbstractController类提供了必须返回视图名称的方法。我问了一个问题:stackoverflow.com/questions/41016018/…,如果您对如何解决我的问题有一些想法,请发表评论。
nowszy94 '16

1

除此之外,返回类型由

  1. HTTP请求说了什么-在其Accept标头中。尝试查看初始请求,以了解“接受”设置为什么。

  2. Spring设置的HttpMessageConverters。如果Jackson类库位于类路径中,Spring MVC将为XML(使用JAXB)和JSON设置转换器。

如果可以选择,则选择一个-在此示例中,它恰好是JSON。

覆盖在课程笔记。查找有关消息转换器和内容协商的注释。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.