restcontroller requestmapping postmapping example ejemplo consumes spring rest spring-mvc spring-3 spring-4

spring - postmapping - MĂșltiples escenarios @RequestMapping produce JSON/XML junto con Accept o ResponseEntity



spring consumes json example (3)

He preferido usar el filtro params para el tipo de contenido centrado en parámetros. Creo que debería funcionar junto con el atributo produce.

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

Estoy trabajando con Spring 4.0.7

Acerca de Spring MVC, con fines de investigación, tengo lo siguiente:

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

Cada uno funciona bien, observe ambos para JSON, con y sin extensión:

  • / getjsonperson
  • /getperson.json

Lo mismo para 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(); }

Cada uno funciona bien, observe ambos para XML, con y sin extensión:

  • / getxmlperson
  • /getperson.xml

Ahora, sobre Restful , tengo lo siguiente:

@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 el MediaType , está mezclado, para JSON y XML

A través de RestTemplate puedo indicar el valor de 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 );

Hasta aquí, por lo tanto, puedo usar una URL / URI para obtener datos en formatos XML o JSON. Funciona bien

Mi problema es con Spring MVC ... solo considera

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

Puedo llamar o activar ese método de manejo ( @RequestMapping ) a través de:

  1. jQuery trabajando con Ajax, puedo indicar el valor de Accept (JSON, por ejemplo)
  2. Poster , a través del botón Headers , puedo configurar Accept

Pregunta uno:

¿Pero para un enlace común? cómo puedo configurar el valor de Accept ? ¿es posible?

Pensé de otra manera en resolver este problema.

  • http://localhost:8080/spring-utility/person/getpersonformat?format=json
  • http://localhost:8080/spring-utility/person/getpersonformat?format=xml

Observar:

  • ?format

Por lo tanto

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

Pregunta dos:

¿Qué código para el método mostrado arriba se debe agregar para personalizar el formato del tipo de devolución? Quiero decir, JSON o XML, ¿es posible?

Pensé en lo siguiente:

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

Pero:

Si ejecuto la URL:

  • http://localhost:8080/spring-utility/person/getpersonformataltern?format=json

yo obtengo

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <person> <id>1</id> <firstName>Manuel</firstName> <lastName>Jordan</lastName> … </person>

¡Sí en XML !

Nota : Puedo confirmar que la consola imprime Ok JSON

Si ejecuto la URL:

  • http://localhost:8080/spring-utility/person/getpersonformataltern?format=xml

yo obtengo

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>

Pregunta tres

¿Qué código para el método mostrado arriba se debe agregar para corregir la salida JSON? No sé lo que está mal o falta.

Hay tres preguntas

Gracias

Alfa

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


Todos sus problemas son que está mezclando la negociación del tipo de contenido con el paso de parámetros. Son cosas en diferentes niveles. Más específico, para su pregunta 2, construyó el encabezado de respuesta con el tipo de medio que desea devolver. La negociación de contenido real se basa en el tipo de medio aceptado en el encabezado de su solicitud, no en el encabezado de respuesta. En el momento en que la ejecución llega a la implementación del método getPersonFormat, no estoy seguro de si la negociación del contenido se ha realizado o no. Depende de la implementación. Si no es así y desea que la cosa funcione, puede sobrescribir el tipo de aceptación del encabezado de solicitud con lo que desea devolver.

return new ResponseEntity <> (PersonFactory.createPerson (), httpHeaders, HttpStatus.OK);


Usar el encabezado Aceptar es realmente fácil de obtener el formato json o xml del servicio REST.

Este es mi controlador, eche un vistazo a la sección de producción.

@RequestMapping(value = "properties", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, method = RequestMethod.GET) public UIProperty getProperties() { return uiProperty; }

Para consumir el servicio REST, podemos usar el siguiente código donde el encabezado puede ser MediaType.APPLICATION_JSON_VALUE o 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();

Editar 01:

Para trabajar con application/xml , agregue esta dependencia

<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>