spring 多个场景@RequestMapping 与 Accept 或 ResponseEntity 一起生成 JSON/XML
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26676613/
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
Multiple scenarios @RequestMapping produces JSON/XML together with Accept or ResponseEntity
提问by Manuel Jordan
I am working with Spring 4.0.7
我正在使用 Spring 4.0.7
About Spring MVC, for research purposes, I have the following:
关于 Spring MVC,出于研究目的,我有以下几点:
@RequestMapping(value="/getjsonperson",
method=RequestMethod.GET,
produces=MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Person getJSONPerson(){
logger.info("getJSONPerson - getjsonperson");
return PersonFactory.createPerson();
}
@RequestMapping(value="/getperson.json", method=RequestMethod.GET)
public @ResponseBody Person getPersonJSON(){
logger.info("getPerson - getpersonJSON");
return PersonFactory.createPerson();
}
Each one works fine, observe both for JSON, with and without extension:
每个都工作正常,观察 JSON,有无扩展名:
- /getjsonperson
- /getperson.json
- /getjsonperson
- /getperson.json
Same for XML
XML 也一样
@RequestMapping(value="/getxmlperson",
method=RequestMethod.GET,
produces=MediaType.APPLICATION_XML_VALUE
)
public @ResponseBody Person getXMLPerson(){
logger.info("getXMLPerson - getxmlperson");
return PersonFactory.createPerson();
}
@RequestMapping(value="/getperson.xml", method=RequestMethod.GET)
@ResponseBody
public Person getPersonXML(){
logger.info("getPerson - getpersonXML");
return PersonFactory.createPerson();
}
Each one works fine, observe both for XML, with and without extension:
每个都工作正常,观察 XML,有无扩展名:
- /getxmlperson
- /getperson.xml
- /getxmlperson
- /getperson.xml
Now about RestfulI have the following:
现在关于Restful我有以下几点:
@RequestMapping(value="/person/{id}/",
method=RequestMethod.GET,
produces={MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<Person> getPersonCustomizedRestrict(@PathVariable Integer id){
Person person = personMapRepository.findPerson(id);
return new ResponseEntity<>(person, HttpStatus.FOUND);//302
}
Observe the MediaType, it is mixed, for JSON and XML
观察MediaType,它是混合的,对于 JSON 和 XML
Through RestTemplateI can indicate the Acceptvalue
通过RestTemplate我可以指示Accept值
if(type.equals("JSON")){
logger.info("JSON");
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
}
else if(type.equals("XML")){
logger.info("XML");
headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML));
}
….
ResponseEntity<Person> response =
restTemplate.exchange("http://localhost:8080/spring-utility/person/{id}/customizedrestrict",
HttpMethod.GET,
new HttpEntity<Person>(headers),
Person.class,
id
);
Until here, therefore I am able to use one URL/URI to get some data in either XML or JSON formats. It works fine
到这里为止,因此我可以使用一个 URL/URI 来获取一些 XML 或 JSON 格式的数据。它工作正常
My problem is with Spring MVC … just consider
我的问题是 Spring MVC ......考虑一下
@RequestMapping(value="/{id}/person",
method=RequestMethod.GET,
produces={MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE})
public @ResponseBody Person getPerson(@PathVariable Integer id){
return personMapRepository.findPerson(id);
}
I can call or activate that handler method (@RequestMapping) through:
我可以@RequestMapping通过以下方式调用或激活该处理程序方法 ( ):
- jQuery working with Ajax, I am able to indicate the
Acceptvalue (JSON for example) - Poster, through the
Headersbutton, I can set theAccept
- jQuery 与 Ajax 一起使用,我能够指示
Accept值(例如 JSON) - 海报,通过
Headers按钮,我可以设置Accept
Question One:
问题一:
But for a common link? how I can set the Acceptvalue? is possible?
但是对于一个共同的链接?我如何设置Accept值?可能吗?
I thought in other way to around this problem.
我想以其他方式解决这个问题。
http://localhost:8080/spring-utility/person/getpersonformat?format=jsonhttp://localhost:8080/spring-utility/person/getpersonformat?format=xml
http://localhost:8080/spring-utility/person/getpersonformat?format=jsonhttp://localhost:8080/spring-utility/person/getpersonformat?format=xml
Observe:
观察:
?format
?format
Therefore
所以
@RequestMapping(value="/getpersonformat",
method=RequestMethod.GET,
produces={MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE})
public @ResponseBody Person getPerson(@RequestParam String format){
return personMapRepository.findPerson(id);
}
Question Two:
问题二:
What code for the method shown above must be added to customize the return type format? I mean, JSON or XML, Is possible?
上面显示的方法必须添加哪些代码才能自定义返回类型格式?我的意思是,JSON 或 XML,可能吗?
I thought in the following:
我想到了以下几点:
@RequestMapping(value="/getpersonformataltern",
method=RequestMethod.GET
produces={MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE}
)
public ResponseEntity<Person> getPersonFormat(@RequestParam String format){
logger.info("getPersonFormat - format: {}", format);
HttpHeaders httpHeaders = new HttpHeaders();
if(format.equals("json")){
logger.info("Ok JSON");
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
}
else{
logger.info("Ok XML");
httpHeaders.setContentType(MediaType.APPLICATION_XML);
}
return new ResponseEntity<>(PersonFactory.createPerson(), httpHeaders, HttpStatus.OK);
}
But:
但:
If I execute the URL:
如果我执行 URL:
http://localhost:8080/spring-utility/person/getpersonformataltern?format=json
http://localhost:8080/spring-utility/person/getpersonformataltern?format=json
I get
我得到
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
<id>1</id>
<firstName>Manuel</firstName>
<lastName>Jordan</lastName>
…
</person>
Yes in XML!
是的在XML 中!
Note: I can confirm the Console prints Ok JSON
注意:我可以确认控制台打印Ok JSON
If I execute the URL:
如果我执行 URL:
http://localhost:8080/spring-utility/person/getpersonformataltern?format=xml
http://localhost:8080/spring-utility/person/getpersonformataltern?format=xml
I get
我得到
This XML file does not appear to have any style information associated with it.
The document tree is shown below.
<person>
<id>1</id>
<firstName>Manuel</firstName>
<lastName>Jordan</lastName>
…
</person>
Question Three
问题三
What code for the method shown above must be added to fix the JSON output? I don't know what is wrong or is missing..
必须为上面显示的方法添加哪些代码才能修复 JSON 输出?我不知道出了什么问题或遗漏了什么..
There are three questions.
有三个问题。
Thank You
谢谢你
Alpha
Α
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
Map<String,MediaType> mediaTypes = new LinkedHashMap<>();
mediaTypes.put("json", MediaType.APPLICATION_JSON);
mediaTypes.put("xml", MediaType.APPLICATION_XML);
configurer.mediaTypes(mediaTypes);
configurer.defaultContentType(MediaType.TEXT_HTML);
}
回答by Eddú Meléndez
Using Accept header is really easy to get the format json or xml from the REST service.
使用 Accept 头可以很容易地从 REST 服务中获取格式 json 或 xml。
This is my Controller, take a look produces section.
这是我的控制器,看看生产部分。
@RequestMapping(value = "properties", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, method = RequestMethod.GET)
public UIProperty getProperties() {
return uiProperty;
}
In order to consume the REST service we can use the code below where header can be MediaType.APPLICATION_JSON_VALUE or MediaType.APPLICATION_XML_VALUE
为了使用 REST 服务,我们可以使用下面的代码,其中 header 可以是 MediaType.APPLICATION_JSON_VALUE 或 MediaType.APPLICATION_XML_VALUE
HttpHeaders headers = new HttpHeaders();
headers.add("Accept", header);
HttpEntity entity = new HttpEntity(headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange("http://localhost:8080/properties", HttpMethod.GET, entity,String.class);
return response.getBody();
Edit 01:
编辑01:
In order to work with application/xml, add this dependency
为了使用application/xml,添加此依赖项
<dependency>
<groupId>com.fasterxml.Hymanson.dataformat</groupId>
<artifactId>Hymanson-dataformat-xml</artifactId>
</dependency>
回答by jljl
All your problems are that you are mixing content type negotiation with parameter passing. They are things at different levels. More specific, for your question 2, you constructed the response header with the media type your want to return. The actual content negotiation is based on the accept media type in your request header, not response header. At the point the execution reaches the implementation of the method getPersonFormat, I am not sure whether the content negotiation has been done or not. Depends on the implementation. If not and you want to make the thing work, you can overwrite the request header accept type with what you want to return.
您所有的问题都在于您将内容类型协商与参数传递混合在一起。它们是不同层次的事物。更具体地说,对于您的问题 2,您使用要返回的媒体类型构建了响应标头。实际的内容协商基于请求标头中的接受媒体类型,而不是响应标头。在执行到达方法 getPersonFormat 的实现时,我不确定内容协商是否已经完成。取决于实施。如果没有并且您想让它工作,您可以用您想要返回的内容覆盖请求标头接受类型。
return new ResponseEntity<>(PersonFactory.createPerson(), httpHeaders, HttpStatus.OK);
返回新的ResponseEntity<>(PersonFactory.createPerson(), httpHeaders, HttpStatus.OK);
回答by M. Maraist
I've preferred using the params filter for parameter-centric content-type.. I believe that should work in conjunction with the produces attribute.
我更喜欢将 params 过滤器用于以参数为中心的内容类型。我相信这应该与生产属性一起使用。
@GetMapping(value="/person/{id}/",
params="format=json",
produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Person> getPerson(@PathVariable Integer id){
Person person = personMapRepository.findPerson(id);
return ResponseEntity.ok(person);
}
@GetMapping(value="/person/{id}/",
params="format=xml",
produces=MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<Person> getPersonXML(@PathVariable Integer id){
return GetPerson(id); // delegate
}

