【问题标题】:Spring 4 @RequestMapping -- consumes vs headers?Spring 4 @RequestMapping - 消耗 vs 标头?
【发布时间】:2015-09-04 13:22:58
【问题描述】:

我正在学习如何使用 Spring 4 构建 RESTful Web 服务,而我不清楚的一件事是在 @RequestMapping 中。我已经看到使用 headers = "Accept=application/xml" 的示例和使用消耗(或生成)= "application/xml" 的其他示例。

例如,在我自己的@RestController 类中,我有这个功能...

// POST
@RequestMapping(method = RequestMethod.POST, headers = "Accept=application/xml")
public User create(@RequestBody User user) {
    LOG.info("User = " + user.toString());
return userService.create(user);
}

使用 headers = "Accept=application/xml" 与使用消耗 = "application/xml"? 甚至使用 headers = "content-type=application/xml" 有什么区别?

有人能解释一下标头和消费/生产之间的区别,以及何时使用它们吗?

【问题讨论】:

    标签: java spring rest spring-mvc


    【解决方案1】:

    简短回答
    在上面的示例中,使用 headers = "Accept=application/xml"produces = "application/xml" 都将以相同的方式响应客户端,即使用 XML 表示向客户端发送响应。

    更长的答案
    我。标题
    对于 RESTful Web 服务,客户端(例如您的浏览器)向服务器发送请求(例如 GET、POST 等),服务器将返回响应。这是一个 HTTP 事务。请求和响应都有 HTTP 标头字段(“headers”),它定义了 HTTP 事务的操作参数(我将客户端请求的标头称为“请求标头”,这些与来自服务器响应的标头“响应”不同标题")。

    作为浏览器向服务器发送的请求的一部分,有不同的请求标头,一些示例包括 AcceptConnectionContent-Length 等,每个标头都有自己的功能(请参阅完整列表这里的标题:https://en.wikipedia.org/wiki/List_of_HTTP_header_fields)。

    使用您的代码示例,如果客户端发出 POST 请求,Spring 将检查请求标头,如果发现标头 Accept 的值为 application/xml,它会将请求映射到 @ 987654331@ 上面的方法(在您的情况下,服务器将向客户端返回 XML 响应表示)。

    让我修改您提供的代码中的headers 元素:

    @RequestMapping(method = RequestMethod.POST, headers = "Connection=keep-alive")
    public User create(@RequestBody User user) {
     ...
    }
    

    注意headers 元素现在的值为Connection=keep-alive。如果客户端发出 POST 请求,Spring 将检查请求标头,如果找到值为 keep-alive 的标头 Connection,它将将该客户端请求映射到上面的 create 方法。

    ii.生产和消费
    如果您将produces="application/xml" 用于create 方法,这意味着只有当客户端的Accept 标头与application/xml 匹配时,客户端请求才会映射到create 方法。这实质上是客户端说,“嘿,服务器,我更愿意接受您以 XML 表示形式的响应,所以将您的响应以 XML 形式发送给我”。实际上,produces="application/xml" 也是服务器在说,“嘿,客户端,我只能以 XML 表示形式为您生成响应,所以我将向您发送该格式”。 Link to Spring documentation reference.

    如果您将consumes="application/xml" 用于create 方法,这意味着如果客户端的Content-Type 标头与application/xml 匹配,则客户端请求仅映射到create 方法(Content-Type 请求标头描述了表示客户端请求即将到来)。这实质上是服务器在说,“嘿,客户端,我只能使用 XML 表示的请求,所以将该格式发送给我”。

    总结
    @RequestMapping 注解中的 headers 元素可以采用不同的请求标头(AcceptConnectionCache-Control 等),但 produces 元素仅与 Accept 请求标头和consumes 元素只关心Content-Type 请求头。

    【讨论】:

    • 此答案应标记为接受答案。顺便感谢亚历克斯提供的详细而翔实的答案。
    • 知道为什么this is not working
    【解决方案2】:

    正如HeadersRequestCondition 的javadoc(处理@RequestMapping 注释的headers 属性中提供的值)状态

    传递给构造函数的表达式具有标头名称“Accept”或 “内容类型”被忽略。请参阅ConsumesRequestConditionProducesRequestCondition 那些。

    所以不要在headers 中使用这些标题。对AcceptContent-Type 使用producesconsumes 属性。

    至于如何使用,文档给出了示例:for consumesfor produces

    【讨论】:

    • 我不认为它被忽略了,官方文档中没有任何关于它的内容。而且它确实有效。无论如何,最好使用生产和消费。
    • @VadimKirilchuk 它们在HeadersRequestCondition 中被忽略。请参阅源代码here。但是,在为RequestMappingHandlerMapping 构建RequestMappingInfo 时,这些相同的值也会传递给ProducesRequestConditionConsumesRequestCondition。见here
    • @VadimKirilchuk 另外,答案中的引用来自 javadoc。
    • 我们之间有点误会。我完全同意 HeaderRequestCondition 忽略 Accept 和 Content-type 标头的观点,我们确实在源代码中看到了这一点。但是最初的问题是关于将标题放在“headers”参数中并且它完美地工作,只是因为正如你所说的“听众”也传递给ProducesRequestCondition抱歉混淆:)
    猜你喜欢
    • 1970-01-01
    • 2016-03-29
    • 2023-03-23
    • 2016-05-03
    • 2016-02-19
    • 2011-06-25
    • 2013-04-25
    • 2017-06-16
    • 2019-05-14
    相关资源
    最近更新 更多