Je me demandais comment implémenter correctement un contrôleur Spring censé servir de service REST. Surtout je veux essayer de rendre l'interface aussi RESTful que possible. De plus, j'aimerais utiliser les codes d'erreur HTTP afin que mes clients puissent agir en conséquence.
Je me demandais comment implémenter mes méthodes afin de renvoyer JSON si tout fonctionne bien (dans le corps de la réponse) ou d'envoyer un code d'erreur http ainsi qu'une raison personnalisée pour laquelle cela ne fonctionne pas la base de données). Cependant, je ne sais pas laquelle est la bonne? renvoyer une chaîne et ajouter les valeurs pour retourner à un modèle, ou renvoyer une table de hachage et y placer mes éléments? ou renvoyer les objets directement? mais alors que se passe-t-il si une erreur survient et que je ne peux pas retourner ladite classe? retourne null à la place? Je publie 2 ou 3 façons de le faire que je pourrais imaginer:
@RequestMapping(value="/addUser", method= RequestMethod.POST)
public String addUser(@RequestBody User user, HttpServletResponse response, Model model) throws Exception{
try{
userService.addUser(user);
model.addAttribute("user", userService.getUser(user.getUsername(), user.getPassword()));
return "user";
}catch(Exception e){
model.addAttribute("error", e.toString());
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString());
return "error";
}
}
Ou plutôt de cette façon:
@RequestMapping(value="/addUser", method= RequestMethod.POST)
public @ResponseBody Map addUser(@RequestBody User user, HttpServletResponse response){
Map map = new HashMap();
try{
userService.addUser(user);
map.put("success", true);
map.put("username", user.getUsername());
}catch (KeyAlreadyExistsException e){
map.put("success", false);
map.put("Error", e.toString());
response.sendError(HttpServletResponse.SC_FORBIDDEN, e.toString());
}catch(Exception e){
map.put("success", false);
map.put("Error", e.toString());
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString());
}
finally {
return map;
}
}
Je réalise que le code n'est pas "juste comme il faut" mais je n'arrive pas à comprendre comment le rendre comme il se doit. Peut-être que certaines expériences pourraient aider? Merci pour le support déjà
Vous pouvez également intercepter vos exceptions avec @ExceptionHandler
méthos annoté dans votre Rest Controller.
@ExceptionHandler(Exception.class)
@ResponseBody
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleException(Exception e) {
return "return error object instead";
}
cela rendra votre contrôleur/contrôleur logique complet plus propre.
Premièrement, je pense que vous devriez toujours renvoyer un objet lors du renvoi de JSON. Même quand quelque chose se passe horriblement mal.
En cas de problème, définissez simplement response.setStatus()
et renvoyez une ressource décrivant l'erreur.
public class ErrorResource implements Resource {
private final int status;
private final String message;
public ErrorResource(int s, String m) {
status = s;
message = m;
}
public int getStatus() {
return status;
}
public String getMessage() {
return message;
}
}
La ressource devient sérialisée et le résultat serait
{"status":500, "message":"Yay!"}
L'utilisation de Map
fonctionnera, mais j'aimerais vous conseiller d'écrire des classes de ressources qui définissent l'objet à renvoyer. Ils seraient plus faciles à entretenir. Maps
n'offre aucune structure alors que la structure est une partie très importante lors de la création d'un service REST
Je ne pense pas que vous devriez renvoyer une ressource avec le message d'exception brut incorporé. Il peut potentiellement laisser échapper des informations que vous ne voulez pas que quiconque voie.
vous pouvez utiliser @ExceptionHandler
avec @ControllerAdvice
vérifier ceci link
utilisez la classe ResponseEntity pour exploiter l'erreur avec le code d'état http.
Vous pouvez essayer le code suivant:
@RequestMapping(value = "/profile", method = RequestMethod.GET)
@ResponseBody @ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<UserVO> getUserProfile()
{
string userName = getUserAuthentication().getName();
if (StringUtils.isEmpty(userName)) RestUtil.defaultJsonResponse("");
User user = userService.getUserByUserNameWithCounters(userName);
return RestUtil.getJsonResponse(new UserVO(user));
}
Si vous souhaitez que l'ensemble de votre exception avec stackTrace soit transmise à votre client, @Bart a déclaré que vous devriez envoyer un objet "ErrorResource".
Une bibliothèque a dans le commerce:
<dependency>
<groupId>com.github.zg2pro</groupId>
<artifactId>spring-rest-basis</artifactId>
<version>0.2</version>
</dependency>
ajoutez-le à votre projet puis ajoutez simplement une classe "@ControllerAdvice" à vos beans, comme expliqué dans le projet wiki .
Cela devrait gérer vos erreurs bien!