responseentity resource requestentity pom getbody example error spring spring-mvc spring-3 spring-4

resource - Cuando use ResponseEntity<T> y @RestController para aplicaciones Spring RESTful



responseentity spring boot example (4)

De acuerdo con la documentación oficial: Creación de controladores REST con la anotación @RestController

@RestController es una anotación de estereotipo que combina @ResponseBody y @Controller. Más que eso, le da más significado a su Controlador y también puede llevar una semántica adicional en futuras versiones del marco.

Parece que es mejor usar @RestController para mayor claridad, pero también puede combinarlo con ResponseEntity para mayor flexibilidad cuando sea necesario ( De acuerdo con el tutorial oficial y el código aquí y mi pregunta para confirmarlo ).

Por ejemplo:

@RestController public class MyController { @GetMapping(path = "/test") @ResponseStatus(HttpStatus.OK) public User test() { User user = new User(); user.setName("Name 1"); return user; } }

es lo mismo que:

@RestController public class MyController { @GetMapping(path = "/test") public ResponseEntity<User> test() { User user = new User(); user.setName("Name 1"); HttpHeaders responseHeaders = new HttpHeaders(); // ... return new ResponseEntity<>(user, responseHeaders, HttpStatus.OK); } }

De esta manera, puede definir ResponseEntity solo cuando sea necesario.

Actualizar

Puedes usar esto:

return ResponseEntity.ok().headers(responseHeaders).body(user);

Estoy trabajando con Spring Framework 4.0.7, junto con MVC y Rest

Puedo trabajar en paz con:

  • @Controller
  • ResponseEntity<T>

Por ejemplo:

@Controller @RequestMapping("/person") @Profile("responseentity") public class PersonRestResponseEntityController {

Con el método (solo para crear)

@RequestMapping(value="/", method=RequestMethod.POST) public ResponseEntity<Void> createPerson(@RequestBody Person person, UriComponentsBuilder ucb){ logger.info("PersonRestResponseEntityController - createPerson"); if(person==null) logger.error("person is null!!!"); else logger.info("{}", person.toString()); personMapRepository.savePerson(person); HttpHeaders headers = new HttpHeaders(); headers.add("1", "uno"); //http://localhost:8080/spring-utility/person/1 headers.setLocation(ucb.path("/person/{id}").buildAndExpand(person.getId()).toUri()); return new ResponseEntity<>(headers, HttpStatus.CREATED); }

devolver algo

@RequestMapping(value="/{id}", method=RequestMethod.GET) public ResponseEntity<Person> getPerson(@PathVariable Integer id){ logger.info("PersonRestResponseEntityController - getPerson - id: {}", id); Person person = personMapRepository.findPerson(id); return new ResponseEntity<>(person, HttpStatus.FOUND); }

Funciona bien

Puedo hacer lo mismo con :

  • @RestController (Sé que es lo mismo que @Controller + @ResponseBody )
  • @ResponseStatus

Por ejemplo:

@RestController @RequestMapping("/person") @Profile("restcontroller") public class PersonRestController {

Con el método (solo para crear)

@RequestMapping(value="/", method=RequestMethod.POST) @ResponseStatus(HttpStatus.CREATED) public void createPerson(@RequestBody Person person, HttpServletRequest request, HttpServletResponse response){ logger.info("PersonRestController - createPerson"); if(person==null) logger.error("person is null!!!"); else logger.info("{}", person.toString()); personMapRepository.savePerson(person); response.setHeader("1", "uno"); //http://localhost:8080/spring-utility/person/1 response.setHeader("Location", request.getRequestURL().append(person.getId()).toString()); }

devolver algo

@RequestMapping(value="/{id}", method=RequestMethod.GET) @ResponseStatus(HttpStatus.FOUND) public Person getPerson(@PathVariable Integer id){ logger.info("PersonRestController - getPerson - id: {}", id); Person person = personMapRepository.findPerson(id); return person; }

Mis preguntas son:

  1. cuando por una razón sólida o escenario específico, una opción debe usarse obligatoriamente sobre la otra
  2. Si (1) no importa, qué enfoque se sugiere y por qué.

Para completar la respuesta de Sotorios Delimanolis.

Es cierto que ResponseEntity le brinda más flexibilidad, pero en la mayoría de los casos no lo necesitará y terminará con estos ResponseEntity en todas partes en su controlador, lo que dificulta su lectura y comprensión.

Si desea manejar casos especiales como errores (No encontrado, Conflicto, etc.), puede agregar un HandlerExceptionResolver a su configuración de Spring. Entonces, en su código, simplemente lanza una excepción específica ( NotFoundException por ejemplo) y decide qué hacer en su controlador (estableciendo el estado HTTP en 404), haciendo que el código del controlador sea más claro.


Una API REST adecuada debería tener los siguientes componentes en respuesta

  1. Código de estado
  2. Cuerpo de respuesta
  3. Ubicación del recurso que se modificó (por ejemplo, si se creó un recurso, el cliente estaría interesado en conocer la URL de esa ubicación)

El objetivo principal de ResponseEntity era proporcionar la opción 3, las opciones de descanso se podían lograr sin ResponseEntity.

Entonces, si desea proporcionar la ubicación del recurso, usar ResponseEntity sería mejor, de lo contrario, se puede evitar.

Considere un ejemplo en el que se modifica una API para proporcionar todas las opciones mencionadas

// Step 1 - Without any options provided @RequestMapping(value="/{id}", method=RequestMethod.GET) public @ResponseBody Spittle spittleById(@PathVariable long id) { return spittleRepository.findOne(id); } // Step 2- We need to handle exception scenarios, as step 1 only caters happy path. @ExceptionHandler(SpittleNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public Error spittleNotFound(SpittleNotFoundException e) { long spittleId = e.getSpittleId(); return new Error(4, "Spittle [" + spittleId + "] not found"); } // Step 3 - Now we will alter the service method, **if you want to provide location** @RequestMapping( method=RequestMethod.POST consumes="application/json") public ResponseEntity<Spittle> saveSpittle( @RequestBody Spittle spittle, UriComponentsBuilder ucb) { Spittle spittle = spittleRepository.save(spittle); HttpHeaders headers = new HttpHeaders(); URI locationUri = ucb.path("/spittles/") .path(String.valueOf(spittle.getId())) .build() .toUri(); headers.setLocation(locationUri); ResponseEntity<Spittle> responseEntity = new ResponseEntity<Spittle>( spittle, headers, HttpStatus.CREATED) return responseEntity; } // Step4 - If you are not interested to provide the url location, you can omit ResponseEntity and go with @RequestMapping( method=RequestMethod.POST consumes="application/json") @ResponseStatus(HttpStatus.CREATED) public Spittle saveSpittle(@RequestBody Spittle spittle) { return spittleRepository.save(spittle); }

Fuente - Primavera en acción


ResponseEntity está destinado a representar la respuesta HTTP completa. Puede controlar todo lo que entra: código de estado, encabezados y cuerpo.

@ResponseBody es un marcador para el cuerpo de respuesta HTTP y @ResponseStatus declara el código de estado de la respuesta HTTP.

@ResponseStatus no es muy flexible. Marca todo el método, por lo que debe asegurarse de que su método de controlador siempre se comportará de la misma manera. Y todavía no puedes configurar los encabezados. Necesitaría el HttpServletResponse o un parámetro HttpHeaders .

Básicamente, ResponseEntity te permite hacer más.