Spring Boot 控制器内容协商

新手上路,请多包涵

我有一个用 Spring-boot 应用程序编写的简单 REST 控制器,但我不确定如何实现内容协商以使其根据请求标头中的 Content-Type 参数返回 JSON 或 XML。有人可以向我解释一下,我做错了什么吗?

控制器方法:

 @RequestMapping(value = "/message", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
  public Message getMessageXML(@RequestParam("text") String text) throws Exception {
    Message message = new Message();
    message.setDate(new Date());
    message.setName("Test");
    message.setAge(99);
    message.setMessage(text);

    return message;
  }

调用此方法时我总是得到 JSON(即使我将 Content-Type 指定为 application/xmltext/xml )。

当我实现两种分别具有不同映射和不同内容类型的方法时,我能够从 xml 中获取 XML,但如果我在单个方法中指定两个 mediaType(如提供的示例),则它不起作用。

我想要的是调用 \message 端点并接收

  • 当 GET 请求的 Content-Type 设置为 application/xml 时的 XML
  • Content-Type 为 application/json 时的 JSON

任何帮助表示赞赏。

编辑:我更新了我的控制器以接受所有媒体类型

@RequestMapping(value = "/message", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE }, consumes = MediaType.ALL_VALUE)
  public Message getMessageXML(@RequestParam("text") String text) throws Exception {
    Message message = new Message();
    message.setDate(new Date());
    message.setName("Vladimir");
    message.setAge(35);
    message.setMessage(text);

    return message;
  }

原文由 Smajl 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 382
2 个回答

您可以在博客文章 @RequestMapping with Produces and Consumes 中的第 6 点找到一些提示。

注意有关 Content-Type 和 Accept 标头的部分:

@RequestMapping with Produces and Consumes:我们可以使用标头 Content-Type 和 Accept 来找出请求内容以及它想要响应的 mime 消息是什么。为清楚起见,@RequestMapping 提供了生产者和消费者变量,我们可以在其中指定将为其调用方法的请求内容类型和响应内容类型。例如:

 @RequestMapping(value="/method6", produces={"application/json","application/xml"}, consumes="text/html")
@ResponseBody
public String method6(){
    return "method6";
}

上述方法只能使用 Content-Type 为 text/html 的消息,并且能够生成 application/json 和 application/xml 类型的消息。

您也可以尝试 这种 不同的方法(使用 ResponseEntity 对象),它允许您找出传入的消息类型并生成相应的消息(也利用 @ResponseBody 注释)

原文由 abarisone 发布,翻译遵循 CC BY-SA 4.0 许可协议

您可以使用 ContentNegotiationConfigurer

首先,您应该覆盖配置类中的 configureContentNegotiation 方法:

 @Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.favorPathExtension(false).
            favorParameter(true).
            defaultContentType(MediaType.APPLICATION_JSON).
            mediaType("xml", MediaType.APPLICATION_XML);
    }
}

favorParameter(true) - 启用优先于参数或接受标头的路径表达式。

defaultContentType(MediaType.APPLICATION_JSON) - 设置默认内容类型。这意味着如果您不传递路径表达式,那么 Spring 将生成 JSON 作为响应。

mediaType("xml", MediaType.APPLICATION_XML) - 设置 XML 的路径表达式键。

现在,如果你像这样声明你的控制器:

 @Controller
class AccountController {

    @RequestMapping(value="/accounts", method=RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    public @ResponseBody List<Account> list(Model model, Principal principal) {
        return accountManager.getAccounts(principal) );
    }
}

并将其命名为 localhost:8080/app/accounts.json ,然后 Spring 将生成 JSON 作为响应。因此,如果您调用 localhost:8080/app/accounts.xml 您将收到 XML 响应

您可以 在此处 找到有关此的更多信息。

原文由 Artur Boruński 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题