弹簧启动控制器内容协商

2022-09-01 16:32:34

我有一个简单的REST控制器,写在Spring-boot应用程序中,但我不知道如何实现内容协商,使其基于请求标头中的内容类型参数返回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(即使我指定了 to be or )。Content-Typeapplication/xmltext/xml

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

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

  • 当 GET 请求的内容类型设置为 application/xml 时的 XML
  • 当内容类型为 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;
  }

答案 1

您可以使用 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) );
    }
}

并称之为类似,然后Spring将生成JSON作为响应。因此,如果您调用,您将收到XML响应localhost:8080/app/accounts.jsonlocalhost:8080/app/accounts.xml

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


答案 2

您可以在博客文章中找到一些提示,@RequestMapping第6点的生产和消费

请注意有关内容类型和接受标头的部分:

使用“生成和消耗”@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 和 application/xml 类型的消息。

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