Java Spring boot 控制器内容协商

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33009918/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:09:12  来源:igfitidea点击:

Spring boot controller content negotiation

javarestspring-boot

提问by Smajl

I have a simple REST controller written in a Spring-boot application but I am not sure how to implement the content negotiation to make it return JSON or XML based on the Content-Type parameter in the request header. Could someone explain to me, what am I doing wrong?

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

Controller method:

控制器方法:

@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;
  }

I always get JSON when calling this method (even if I specify the Content-Typeto be application/xmlor text/xml).

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

When I implement two methods each with different mapping and different content type, I am able to get XML from the xml one but it does not work if I specify two mediaTypes in a single method (like the provided example).

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

What I would like is to call the \messageendpoint and receive

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

  • XML when the Content-Type of the GET request is set to application/xml
  • JSON when the Content-Type is application/json
  • GET 请求的 Content-Type 设置为 application/xml 时的 XML
  • 当 Content-Type 为 application/json 时的 JSON

Any help is appreciated.

任何帮助表示赞赏。

EDIT: I updated my controller to accept all media types

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

@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;
  }

采纳答案by abarisone

You can find some hints in the blog post @RequestMapping with Produces and Consumesat point 6.

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

Pay attention to the section about Content-Type and Accept headers:

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

@RequestMapping with Produces and Consumes: We can use header Content-Type and Accept to find out request contents and what is the mime message it wants in response. For clarity, @RequestMapping provides produces and consumes variables where we can specify the request content-type for which method will be invoked and the response content type. For example:

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

Above method can consume message only with Content-Type as text/html and is able to produce messages of type application/json and application/xml.

@RequestMapping with Produces 和 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 的消息。

You can also try thisdifferent approach (using ResponseEntity object) that allows you to find out the incoming message type and produce the corresponding message (also exploiting the @ResponseBody annotation)

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

回答by Artur Boruński

You can use ContentNegotiationConfigurer

您可以使用ContentNegotiationConfigurer

Firstly, you should override the configureContentNegotiationmethod in your configuration class:

首先,您应该覆盖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)- enabling favoring path expressions over parameter or accept headers.

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

defaultContentType(MediaType.APPLICATION_JSON)- sets the default content type. this means that if you don't pass a path expression then Spring will generate JSON as response.

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

mediaType("xml", MediaType.APPLICATION_XML)- sets the path expression key for XML.

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

Now if you declare your Controller like:

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

@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) );
    }
}

and call it something like localhost:8080/app/accounts.json, then Spring will generate JSON as response. So if you call localhost:8080/app/accounts.xmlyou will receive XML response

并将其称为localhost:8080/app/accounts.json,然后 Spring 将生成 JSON 作为响应。所以如果你打电话localhost:8080/app/accounts.xml你会收到 XML 响应

You can find more info about this here.

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