Spring启动控制器内容协商

Sma*_*ajl 16 java rest 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;
  }
Run Code Online (Sandbox Code Playgroud)

调用此方法时,我总是得到JSON(即使我指定了Content-Typeapplication/xml或者text/xml).

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

我想要的是调用\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;
  }
Run Code Online (Sandbox Code Playgroud)

小智 26

您可以使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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) );
    }
}
Run Code Online (Sandbox Code Playgroud)

并称之为localhost:8080/app/accounts.json,然后Spring将生成JSON作为响应.因此,如果您打电话,localhost:8080/app/accounts.xml您将收到XML响应

你可以在这里找到更多相关信息.

  • 我认为这里有一个小错误 - 你声称控制器工作的方式,你应该将favorPathExtension设置为true,而不是favorParameter. (3认同)
  • 另一个小脚注:在Spring启动应用程序中,你的`@Configuration`类应该**不包含`@ EnableWebMvc`注释([source](https://dzone.com/articles/spring-boot-enablewebmvc-和共用例)).它可能会阻止其他工作,例如springfox-swagger-ui html页面. (3认同)
  • 在defaultContentType上只是一个小脚注:[浏览器倾向于发送更喜欢XML的接受标题](https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html) .绕过(假设你没有使用它)可以在你的contentNegotiation覆盖中完成Accept标头:`configurer.ignoreAcceptHeader(true)` (2认同)
  • 对于当前的春季启动版本,请使用“实现WebMvcConfigurer”而不是已弃用的“扩展WebMvcConfigurerAdapter”。 (2认同)

aba*_*one 15

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

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

使用Produces和Consumes进行@RequestMapping:我们可以使用标题Content-Type和Accept来查找请求内容以及它想要响应的mime消息.为清楚起见,@ RequestMapping提供了生成和使用变量,我们可以在其中指定将调用哪个方法的请求内容类型以及响应内容类型.例如:

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

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

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