Несколько сценариев @RequestMapping создает JSON/XML вместе с Accept или ResponseEntity
Я работаю с Spring 4.0.7
О 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();
}
Каждый работает отлично, соблюдайте как JSON, так и без расширения:
- /getjsonperson
- /getperson.json
То же самое для 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();
}
Каждый работает отлично, соблюдайте как XML, так и без расширения:
- /getxmlperson
- /getperson.xml
Теперь о 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
}
Наблюдайте за MediaType
, он смешан, для JSON и XML
Через 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
);
До сих пор я мог использовать один URL/URI для получения некоторых данных в форматах XML или JSON. Он отлично работает
Моя проблема связана с 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);
}
Я могу вызвать или активировать этот метод обработчика (@RequestMapping
) через:
- jQuery, работающий с Ajax, я могу указать значение
Accept
(например, JSON)
- Poster, с помощью кнопки
Headers
я могу установить Accept
Вопрос 1:
Но для общей ссылки? как я могу установить значение Accept
? возможно?
Я думал по-другому обойти эту проблему.
-
http://localhost:8080/spring-utility/person/getpersonformat?format=json
-
http://localhost:8080/spring-utility/person/getpersonformat?format=xml
Обратите внимание:
Поэтому
@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);
}
Вопрос второй:
Какой код для показанного выше метода должен быть добавлен для настройки формата возвращаемого типа?
Я имею в виду, JSON или XML, возможно?
Я подумал:
@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);
}
Но:
Если я выполняю URL-адрес:
-
http://localhost:8080/spring-utility/person/getpersonformataltern?format=json
Я получаю
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
<id>1</id>
<firstName>Manuel</firstName>
<lastName>Jordan</lastName>
…
</person>
Да в XML!
Примечание. Я могу подтвердить распечатку консоли Ok JSON
Если я выполняю URL-адрес:
-
http://localhost:8080/spring-utility/person/getpersonformataltern?format=xml
Я получаю
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>
Вопрос три
Какой код для показанного выше метода должен быть добавлен для исправления вывода JSON?
Я не знаю, что не так или нет.
Есть три вопроса.
Спасибо
Альфа
@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);
}
Ответы
Ответ 1
Использование заголовка Accept действительно легко получить формат json или xml из службы REST.
Это мой контроллер, посмотрите, как выглядит раздел.
@RequestMapping(value = "properties", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, method = RequestMethod.GET)
public UIProperty getProperties() {
return uiProperty;
}
Чтобы использовать услугу REST, мы можем использовать код ниже, где заголовок может быть 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();
Изменить 01:
Чтобы работать с application/xml
, добавьте эту зависимость
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
Ответ 2
Все ваши проблемы в том, что вы смешиваете согласование типа контента с передачей параметров. Это вещи на разных уровнях. Более конкретно, для вашего вопроса 2 вы построили заголовок ответа с типом носителя, который хотите вернуть. Фактическое согласование содержимого основано на типе носителя accept в заголовке запроса, а не на заголовке ответа. В тот момент выполнение достигает реализации метода getPersonFormat, я не уверен, было ли выполнено согласование содержимого или нет. Зависит от реализации. Если нет, и вы хотите, чтобы эта работа работала, вы можете перезаписать тип принятия заголовка запроса с тем, что вы хотите вернуть.
вернуть новый ResponseEntity < > (PersonFactory.createPerson(), httpHeaders, HttpStatus.OK);
Ответ 3
Я предпочел использовать фильтр params для типа содержимого, ориентированного на параметр. Я считаю, что это должно работать в сочетании с атрибутом create.
@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
}