Spring @ResponseBody 注释如何工作?

2022-08-31 10:31:12

我有一个按以下方式注释的方法:

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

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

还阅读了官方的春季文档: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()JSONHttp Response

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


答案 1

首先,注释不注释 。它像注释方法一样。您的代码等效于ListRequestMapping

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

现在,注释的意思是,该方法的返回值将构成 HTTP 响应的主体。当然,HTTP 响应不能包含 Java 对象。因此,此帐户列表将转换为适合 REST 应用程序(通常是 JSON 或 XML)的格式。

格式的选择取决于已安装的消息转换器、批注的 produce 属性的值以及客户端接受的内容类型(在 HTTP 请求标头中可用)。例如,如果请求说它接受 XML,但不接受 JSON,并且安装了一个可以将列表转换为 XML 的消息转换器,则将返回 XML。@RequestMapping


答案 2

要了解的第一件基本事情是体系结构的差异。

一方面,你有MVC架构,它基于你的普通Web应用程序,使用网页,浏览器发出页面请求:

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

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

另一方面,你有一个RESTful架构。在这种情况下,没有视图。控制器仅发回模型(或资源表示,以更 RESTful 的术语)。客户端可以是 JavaScript 应用程序、Java 服务器应用程序,以及我们向其中公开 REST API 的任何应用程序。使用此体系结构,客户端可以决定如何处理此模型。以Twitter为例。Twitter作为Web(REST)API,它允许我们的应用程序使用其API来获取状态更新之类的东西,以便我们可以使用它来将这些数据放在我们的应用程序中。这些数据将以某种格式出现,如JSON。

话虽如此,在与Spring MVC合作时,它最初是为处理基本的Web应用程序架构而构建的。可能有不同的方法签名风格,允许从我们的方法生成视图。该方法可以返回我们显式创建它的位置,或者有隐式方法,我们可以返回一些任意对象,这些对象被设置为模型属性。但无论哪种方式,在请求 - 响应周期的某个地方,都会产生一个视图。ModelAndView

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

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

以设置内容类型,但 JSON 可能是默认类型。不要引用我的话,但是如果你正在获取JSON,并且你还没有指定,那么它可能是默认值。JSON不是唯一的格式。例如,上述内容可以很容易地以XML格式发送,但是您需要具有to,并且我相信您需要为JAXB配置。至于配置的JSON,当我们在类路径上有Jackson时。producesproducesMediaType.APPLICATION_XML_VALUEHttpMessageConverterMappingJacksonHttpMessageConverter

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