Spring启动控制器内容协商

时间:2015-10-08 07:59:26

标签: 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;
  }

我在调用此方法时总是得到JSON(即使我将Content-Type指定为application/xmltext/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;
  }

2 个答案:

答案 0 :(得分:22)

您可以使用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声明为:

@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响应

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

答案 1 :(得分:11)

您可以在第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";
}
     

上述方法只能使用Content-Type作为text / html消息   并能够生成application / json类型的消息   应用/ XML。

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