¿Qué devolver si el método del controlador Spring MVC no devuelve valor?

135

Estoy usando jQuery's $.getJSON()para hacer llamadas asincrónicas a mi simple backend Spring MVC. La mayoría de los métodos del controlador Spring se ven así:

@RequestMapping(value = "/someURL", method = RequestMethod.POST)
public @ResponseBody SomePOJO getSomeData(@ModelAttribute Widget widget,
    @RequestParam("type") String type) {
    return someDAO.getSomeData(widget, type);
}   

Tengo las cosas configuradas para que cada controlador devuelva el @ResponseBodycomo JSON, que es lo que el lado del cliente espera.

Pero, ¿qué sucede cuando se supone que una solicitud no devuelve ningún contenido al lado del cliente? Puedo tener:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
public @ResponseBody void updateDataThatDoesntRequireClientToBeNotified(...) {
    ...
}

Si no, ¿cuál es la sintaxis adecuada para usar aquí?

IAmYourFaja
fuente
Supongo que si no devuelve nada, ¿no se devolverá ningún contenido?
Arahant
1
Creo que aún devolvería un POJO de algún tipo, incluso si en la Versión 1 de su solución simplemente envuelve un booleano de "éxito" o algo similar. Entonces usted tiene un patrón constante en todas sus métodos AJAX, y algo que es más fácil de construir una vez que resulta que haces necesidad de devolver algo!
molino
Al contrario de lo que sugieren las respuestas, lo que tenía por primera vez en su segundo fragmento está perfectamente bien y es la forma correcta de manejar los POSTdatos.
Brett Ryan
En este caso va a devolver nulo. @RestController public class RESTControllerExample {@RequestMapping (value = "/ employee", method = RequestMethod.GET) public void getEmployeeNames () {EmployeeSource.getEmployees (); System.out.println ("Ya terminé"); }}
spandey

Respuestas:

256

puede devolver void, luego debe marcar el método con @ResponseStatus (value = HttpStatus.OK) no necesita @ResponseBody

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void updateDataThatDoesntRequireClientToBeNotified(...) {
    ...
}

Solo los métodos get devuelven una implicidad de código de estado 200, todos los demás que tiene hacen una de tres cosas:

  • Devuelva vacío y marque el método con @ResponseStatus(value = HttpStatus.OK)
  • Devolver un objeto y marcarlo con @ResponseBody
  • Devolver una HttpEntityinstancia
ams
fuente
2
En caso de que ocurra una excepción de tiempo de ejecución en el medio, se devolverá HTTP 500 y no 200. Por lo tanto, si su controlador de front-end falla, el mensaje de excepción / error se mostrará correctamente.
Lee Chee Kiam el
27
En realidad, no necesita configurar @ResponseStatusy no debería. Simplemente tener @ResponseBodyun voidcontrolador es lo suficientemente bueno.
Brett Ryan
11
Creo que será mejor devolver un 204 Sin contenido en lugar de un 200 para métodos nulos
raspacorp
1
@raspacorp 200 es correcto para POST ya que no está destinado a tener un cuerpo.
Brett Ryan
8
@BrettRyan solo como un comentario, al menos para una API REST, es una práctica común que se use una POST para crear contenido, en cuyo caso generalmente devuelve la identificación de las entidades creadas, las entidades creadas completas o un enlace a la operación de lectura. Una devolución de estado 200 sin contenido podría ser confusa desde la perspectiva de la API REST.
raspacorp
43

Simplemente puede devolver una ResponseEntity con el encabezado apropiado:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
public ResponseEntity updateDataThatDoesntRequireClientToBeNotified(...){
....
return new ResponseEntity(HttpStatus.OK)
}
Biju Kunjummen
fuente
En caso de que alguien tuviera el mismo problema que yo, esto no funcionó en una versión anterior de spring (4.1.1), obtendría 500 errores. Actualicé a 4.2.0 y esto funciona muy bien
Salsa
Esa es mi forma preferida de devolver 200 vacías también. Desde Spring 4.1 use el patrón de construcción en su lugar: return ResponseEntity.ok (). Build ();
GreenTurtle
3
Aunque parece compilar, da la siguiente advertenciaResponseEntity is a raw type. References to generic type ResponseEntity<T> should be parameterized
Gonzalo.-
8

Puede devolver el objeto "ResponseEntity". El uso del objeto "ResponseEntity" es muy conveniente tanto al momento de construir el objeto de respuesta (que contiene el cuerpo de respuesta y el código de estado HTTP) como al momento de obtener información del objeto de respuesta.

Métodos como getHeaders (), getBody (), getContentType (), getStatusCode () etc. hacen que el trabajo de leer el objeto ResponseEntity sea muy fácil.

Debe usar el objeto ResponseEntity con un código de estado http de 204 (Sin contenido), que es específicamente para especificar que la solicitud se ha procesado correctamente y que el cuerpo de la respuesta está en blanco intencionalmente. Usar códigos de estado apropiados para transmitir la información correcta es muy importante, especialmente si está creando una API que será utilizada por múltiples aplicaciones cliente.

Harley
fuente
3
configuración @ResponseStatus(HttpStatus.NO_CONTENT)resuelta XML Parsing Error: no root element foundpara mí en el navegador
aliopi
3

Sí, puede usar @ResponseBody con el voidtipo de retorno:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
@ResponseBody
public void updateDataThatDoesntRequireClientToBeNotified(...) {
    ...
}
usuario1338062
fuente
1
Entonces, ¿cuál será el tipo de retorno ... es el código de estado HTTP?
spandey
@techBeginner En este caso 200 (OK).
Lakatos Gyula
2

No hay nada de malo en devolver un vacío @ResponseBodyy debe POSTsolicitarlo.

Use códigos de estado HTTP para definir errores dentro de las rutinas del controlador de excepciones, ya que otros mencionan el estado de éxito. Un método normal como el que tiene devolverá un código de respuesta 200que es lo que desea, cualquier controlador de excepciones puede devolver un objeto de error y un código diferente (es decir 500).

Brett Ryan
fuente
1

Pero a medida que su sistema crece en tamaño y funcionalidad ... creo que devolver siempre un json no es una mala idea. Es más una cuestión arquitectónica / "diseño a gran escala".

Puede pensar en recuperar siempre un JSON con dos campos conocidos: código y datos. Donde el código es un código numérico que especifica el éxito de la operación a realizar y los datos son cualquier dato adicional relacionado con la operación / servicio solicitado.

Vamos, cuando usamos un proveedor de servicios backend, cualquier servicio se puede verificar para ver si funcionó bien.

Así que me quedo, para no dejar que Spring administre esto, exponiendo las operaciones de retorno híbridas (Algunos devuelven datos, otros nada ...). Instaed asegúrese de que su servidor exponga una interfaz más homogénea. Es más simple al final del día.

Víctor
fuente
0

Aquí hay un código de ejemplo de lo que hice para un método asincrónico

@RequestMapping(value = "/import", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void importDataFromFile(@RequestParam("file") MultipartFile file) 
{
    accountingSystemHandler.importData(file, assignChargeCodes);
}

No necesita devolver nada de su método, todo lo que necesita para usar esta anotación es que su método debe devolver OK en todos los casos

@ResponseStatus(value = HttpStatus.OK)
AbdusSalam
fuente