【问题标题】:How to set the response content type dynamically in Spring Rest Controller?如何在 Spring Rest Controller 中动态设置响应内容类型?
【发布时间】:2018-05-09 18:33:33
【问题描述】:

我已经实现了一个 API,它将根据客户端的请求(即请求中的 Accept 标头)返回 JSON 和 XML。它按预期工作。

这里的问题是:即使用户发送 Accept 头,在某些特殊情况下(即业务逻辑)我们需要动态发送响应内容类型。 我曾尝试使用 HttpHeaders 来实现它,但它不起作用。

@GetMapping
public ResponseEntity<Response> getQueries(){
...............

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    //headers.add("Content-Type", "application/json");  
    return new ResponseEntity<Response>(response, headers, HttpStatus.OK);
}

我的 HTTP 状态为 200,但响应为错误,即

Unexpected '<'

如何解决这个问题?

【问题讨论】:

标签: spring rest spring-mvc


【解决方案1】:

您的问题是关于内容协商的,它是一种允许消费者(您的用户代理)和提供者(您的控制器)从一开始就同意响应的媒体类型的能力

首先,由 APi 消费者来指示它将接受什么媒体类型作为响应。这是通过将 Accept 标头设置为所需的类型来完成的。因此,在消费者期望响应类型为 JSON 的情况下,Accept 标头应配置为 XML 的“application/json”或“application/xml”(或每个的任何特定变体,例如“application/xhtml+xml”和一样)。

在控制器端,您需要使用“produces”注释属性指定支持的响应媒体类型。还有一个兄弟“consumes”属性指定支持的请求媒体类型。太好了……我们的映射应该如下所示:

@GetMapping(value="someEndpoint",
        produces={"application/json","application/xml"})
public ResponseEntity<Page<Person>> getPersons(
        @RequestParam(value = "page", required = true) Integer pPage,
        @RequestParam(value = "size", required = true) Integer pSize) 
{
    Page<Person>  result;
    result = personService.getPersons(new PageRequest(pPage, pSize));
    return new ResponseEntity<>(result, HttpStatus.OK);
}

现在有趣的部分是您不必费心响应格式,因为 Spring 将能够根据 http 请求 Accept 标头的值检测消费者所需的响应媒体类型。

更好的是,通过正确的配置,如果请求中没有 Accept 标头,您可以设置默认响应 mediaType。因此,通过将默认响应内容类型设置为“application/json”,任何没有 Accept 标头的请求都将以 JSON 格式提供服务,而消费者必须添加 Accept:“application/xml”才能将响应类型设为 xml。

有关此主题和配置设置的示例和变体,请参阅此Spring guide

希望这会有所帮助,

杰克

【讨论】:

  • 感谢您的回复,但这不是我所期望的。内容协商是检查/忽略 Accept 标头并默认给出响应。我的问题是:如何覆盖 Accept 标头默认/请求并基于业务逻辑如何动态设置响应内容类型?我试过 HTTPHeaders 但没有运气
  • @Krish 我正确理解了你的问题。您的目标是,忽略 Accept 标头并以后端决定的格式进行响应,甚至无需尝试与消费者就普遍支持的格式达成一致。参考 [MDN Content-Negotiation]([developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation]) ,无论你是实现Server或Agent驱动的协商,最终双方必须先商定格式再继续,否则消费者将无法处理响应(re: 200-OK 错误 Unexpected '
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-20
  • 2015-03-10
  • 1970-01-01
相关资源
最近更新 更多