Que renvoyer si la méthode de contrôleur Spring MVC ne renvoie pas de valeur?


135

J'utilise jQuery $.getJSON()pour effectuer des appels asynchrones vers mon backend simple Spring MVC. La plupart des méthodes de contrôleur Spring ressemblent à ceci:

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

J'ai configuré les choses pour que chaque contrôleur renvoie le @ResponseBodyJSON, ce que le client attend.

Mais que se passe-t-il lorsqu'une requête n'est pas censée renvoyer du contenu côté client? Puis-je avoir:

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

Sinon, quelle est la syntaxe appropriée à utiliser ici?


Je suppose que si vous ne retournez rien, aucun contenu ne sera renvoyé?
arahant

1
Je pense que je retournerais toujours un POJO d'une sorte, même si dans la version 1 de votre solution, il encapsule simplement un booléen «succès» ou quelque chose de similaire. Ensuite , vous avez un modèle cohérent dans toutes vos méthodes AJAX, et quelque chose qui est plus facile de construire quand il se avère que vous avez besoin de quelque chose de retour!
moulin du

Contrairement à ce que suggèrent les réponses, ce que vous aviez pour la première fois dans votre deuxième extrait de code est parfaitement correct et constitue la manière correcte de gérer les POSTdonnées.
Brett Ryan

Dans ce cas, il retournera null. @RestController classe publique RESTControllerExample {@RequestMapping (value = "/ Employees", method = RequestMethod.GET) public void getEmployeeNames () {EmployeeSource.getEmployees (); System.out.println ("J'ai fini"); }}
spandey

Réponses:


256

vous pouvez renvoyer void, puis vous devez marquer la méthode avec @ResponseStatus (value = HttpStatus.OK) vous n'avez pas besoin de @ResponseBody

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

Seules les méthodes get renvoient une implicité de code d'état 200, toutes les autres que vous avez font l'une des trois choses suivantes:

  • Renvoyer void et marquer la méthode avec @ResponseStatus(value = HttpStatus.OK)
  • Renvoyer un objet et le marquer avec @ResponseBody
  • Renvoyer une HttpEntityinstance

2
Au cas où une exception d'exécution se produirait entre les deux, HTTP 500 sera renvoyé et non 200. Donc, si votre poignée frontale échoue, le message d'exception / d'erreur s'affichera correctement.
Lee Chee Kiam

27
En fait, vous n'avez pas besoin de définir @ResponseStatuset ne devriez pas. Le simple fait d'avoir @ResponseBodyun voidgestionnaire est assez bien.
Brett Ryan

11
Je pense qu'il sera préférable de renvoyer un 204 No Content au lieu d'un 200 pour les méthodes vides
raspacorp

1
@raspacorp 200 est correct pour POST car il n'est pas censé avoir un corps.
Brett Ryan

8
@BrettRyan juste comme un commentaire, au moins pour une API REST, il est courant qu'un POST soit utilisé pour créer du contenu, auquel cas il retourne généralement l'id de la ou des entités créées, les entités entièrement créées ou un lien à l'opération de lecture. Un retour de statut 200 sans contenu peut être déroutant du point de vue de l'API REST.
raspacorp

43

Vous pouvez simplement renvoyer un ResponseEntity avec l'en-tête approprié:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
public ResponseEntity updateDataThatDoesntRequireClientToBeNotified(...){
....
return new ResponseEntity(HttpStatus.OK)
}

Si quelqu'un rencontrait le même problème que moi, cela ne fonctionnait pas sur une ancienne version de spring (4.1.1), j'obtiendrais 500 erreurs. Je suis passé à la version 4.2.0 et cela fonctionne très bien
sauce

C'est aussi ma façon préférée de rendre 200 vides. Depuis Spring 4.1, utilisez plutôt le modèle de générateur: return ResponseEntity.ok (). Build ();
GreenTurtle

3
Bien que semble compiler, il donne l'avertissement suivantResponseEntity is a raw type. References to generic type ResponseEntity<T> should be parameterized
Gonzalo.-

8

Vous pouvez renvoyer l'objet "ResponseEntity". L'utilisation de l'objet "ResponseEntity" est très pratique à la fois au moment de la construction de l'objet de réponse (qui contient le corps de la réponse et le code d'état HTTP) et au moment de l'extraction des informations de l'objet de réponse.

Des méthodes telles que getHeaders (), getBody (), getContentType (), getStatusCode () etc. facilitent la lecture de l'objet ResponseEntity.

Vous devez utiliser un objet ResponseEntity avec un code d'état http de 204 (Aucun contenu), qui est spécifiquement pour spécifier que la demande a été traitée correctement et que le corps de la réponse est intentionnellement vide. Il est très important d'utiliser des codes d'état appropriés pour transmettre les bonnes informations, en particulier si vous créez une API qui sera utilisée par plusieurs applications clientes.


3
paramètre @ResponseStatus(HttpStatus.NO_CONTENT)résolu XML Parsing Error: no root element foundpour moi dans le navigateur
aliopi

3

Oui, vous pouvez utiliser @ResponseBody avec le voidtype de retour:

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

1
alors quel sera le type de retour .. est-ce un code d'état HTTP?
spandey

@techBeginner Dans ce cas 200 (OK).
Lakatos Gyula

2

Il n'y a rien de mal à renvoyer un vide @ResponseBodyet vous devriez pour les POSTdemandes.

Utilisez plutôt les codes d'état HTTP pour définir les erreurs dans les routines du gestionnaire d'exceptions, car d'autres mentionnent l'état de réussite. Une méthode normale comme vous l'avez retournera un code de réponse 200dont vous avez besoin, tout gestionnaire d'exceptions peut alors retourner un objet d'erreur et un code différent (ie 500).


1

Mais à mesure que votre système grandit en taille et en fonctionnalités ... je pense que retourner toujours un json n'est pas du tout une mauvaise idée. Est plus une question d'architecture / de «conception à grande échelle».

Vous pouvez penser à returing toujours un JSON avec deux champs connus: le code et les données. Où code est un code numérique spécifiant le succès de l'opération à effectuer et les données sont des données supplémentaires liées à l'opération / service demandé.

Allez, quand nous utilisons un backend un fournisseur de services, n'importe quel service peut être vérifié pour voir s'il a bien fonctionné.

Donc je m'en tiens, pour ne pas laisser le printemps gérer cela, exposant des opérations de retour hybrides (Certains retourne des données autre rien ...) .. instaed assurez-vous que votre serveur expose une interface plus homogène. C'est plus simple à la fin de la journée.


0

Voici un exemple de code de ce que j'ai fait pour une méthode asynchrone

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

Vous n'avez pas besoin de renvoyer quoi que ce soit de votre méthode, tout ce dont vous avez besoin pour utiliser cette annotation pour que votre méthode renvoie OK dans tous les cas

@ResponseStatus(value = HttpStatus.OK)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.