Printemps de Démarrage de la liaison et de la validation de la gestion d'erreur dans le contrôleur REST
Quand j'ai le modèle suivant avec la JSR-303 (framework de validation) annotations:
public enum Gender {
MALE, FEMALE
}
public class Profile {
private Gender gender;
@NotNull
private String name;
...
}
et suivants de données JSON:
{ "gender":"INVALID_INPUT" }
Dans mon REPOS contrôleur, je veux gérer à la fois l'erreur de liaison (invalide valeur d'enum pour gender
à la propriété) et les erreurs de validation (name
propriété ne peut pas être null).
Le contrôleur suivant la méthode ne fonctionne PAS:
@RequestMapping(method = RequestMethod.POST)
public Profile insert(@Validated @RequestBody Profile profile, BindingResult result) {
...
}
Cela donne com.fasterxml.jackson.databind.exc.InvalidFormatException
la sérialisation d'erreur avant de liaison ou de validation.
Après quelques tripoter, je suis venu avec ce code personnalisé qui fait ce que je veux:
@RequestMapping(method = RequestMethod.POST)
public Profile insert(@RequestBody Map values) throws BindException {
Profile profile = new Profile();
DataBinder binder = new DataBinder(profile);
binder.bind(new MutablePropertyValues(values));
//validator is instance of LocalValidatorFactoryBean class
binder.setValidator(validator);
binder.validate();
//throws BindException if there are binding/validation
//errors, exception is handled using @ControllerAdvice.
binder.close();
//No binding/validation errors, profile is populated
//with request values.
...
}
Fondamentalement, ce que ce code n'est sérialiser un générique carte au lieu de modèle, puis utiliser le code personnalisé à se lier à des modèle et vérifier les erreurs.
J'ai les questions suivantes:
- Est le code personnalisé à la manière d'aller ici ou est-il plus standard de la manière de le faire au Printemps de Démarrage?
- Comment le
@Validated
annotation de travail? Comment puis-je faire mes propres annotations personnalisées qui fonctionne comme@Validated
pour encapsuler mon custom code de liaison?
OriginalL'auteur Jaap van Hengstum | 2016-01-11
Vous devez vous connecter pour publier un commentaire.
C'est le code que j'ai utilisé dans un de mes projet pour la validation de l'api REST au printemps de démarrage,ce n'est pas la même chose que vous avez demandé,mais est identique.. vérifier si cela permet de
Success.java
Error.java
Vous pouvez aussi jeter un oeil ici : Le printemps RESTE la Validation
OriginalL'auteur al_mukthar
Habituellement, lorsque Spring MVC ne parvient pas à lire les messages http (par exemple, du corps de la requête), il va lancer une instance de
HttpMessageNotReadableException
exception. Donc, si le printemps n'a pas pu lier à votre modèle, il faut jeter cette exception. Aussi, si vous ne PAS définir unBindingResult
après chaque pour-être-modèle validé dans vos paramètres de méthode, dans le cas d'une erreur de validation, le printemps lance laMethodArgumentNotValidException
exception. Avec tout cela, vous pouvez créerControllerAdvice
qui attire ces deux exceptions et les gère dans votre souhaitable.ex.getBindingResult()
surMethodArgumentNotValidException
exception, mais pas sur unHttpMessageNotReadableException
exception.Ce dernier semble raisonnable, car lors de la liaison est-à défaut, nous ne pourrions pas avoir une liaison résultat. Il n'y a pas de liaison.
De mon point de vue de liaison des erreurs comme mettre une Chaîne de caractères dans un champ int ou d'une fausse valeur d'Enum doivent être traités comme des erreurs de validation. À l'aide de
DataBinder
autonome aussi champ liaison erreurs sont dans leBindingResult
de sorte que le service peut renvoyer une erreur plus détaillé de réponse.Je suis d'accord. Je vais avoir un problème en essayant d'afficher correctement un BON message d'erreur lorsque quelqu'un donne une valeur non valide pour un enum. Jackson l'enveloppe et je me retrouve avec un très générique HttpMessageNotReadableException. Le message y inclut le package java et des informations de classe. Pas acceptable. Je veux savoir le champ qui a échoué et pourquoi, mais je ne peux pas trouver un moyen de le faire. J'ai essayé de désactiver le WRAP_EXCEPTIONS, mais qui ne semble pas avoir d'effet
OriginalL'auteur Ali Dehghani
J'ai renoncé à cette question; il est tout simplement pas possible d'obtenir la liaison erreurs à l'aide de
@RequestBody
sans beaucoup de code personnalisé. Ceci est différent de contrôleurs de liaison à la plaine de JavaBeans arguments parce@RequestBody
utilise Jackson de se lier au lieu du Printemps databinder.Voir https://jira.spring.io/browse/SPR-6740?jql=text%20~%20%22RequestBody%20binding%22
OriginalL'auteur Jaap van Hengstum
Vous ne pouvez pas obtenir BindException avec @RequestBody. Pas dans le contrôleur avec un
Errors
paramètre de méthode, comme indiqué ici:Il affirme que, pour
@ModelAttribute
vous obtenez de liaison ET les erreurs de validation et pour votre@RequestBody
vous obtenez erreurs de validation uniquement.https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-methods
Et il a été discuté ici:
https://github.com/spring-projects/spring-framework/issues/11406?jql=text%2520~%2520%2522RequestBody%2520binding%2522
Pour moi il ne fait toujours pas de sens à partir d'un point de vue utilisateur. Il est souvent très important pour obtenir le BindExceptions de montrer à l'utilisateur un message d'erreur approprié. L'argument est, vous devriez faire la validation côté client de toute façon. Mais ce n'est pas vrai si un développeur est à l'aide de l'API directement.
Et imaginez votre côté client, la validation est fondée sur une demande d'API. Vous voulez vérifier si une date donnée est valide en fonction d'un calendrier enregistrées. Vous envoyer la date et l'heure pour le backend et il échoue.
Vous pouvez modifier l'exception que vous obtenez avec un ExceptionHAndler réagir sur HttpMessageNotReadableException, mais avec cette exception que j'ai de ne pas avoir accès à ce qui était le champ de jeter l'erreur qu'avec un BindException. J'ai besoin d'analyser le message d'exception pour y avoir accès.
Donc je ne vois pas de solution, ce qui est une sorte de mal parce que avec
@ModelAttribute
il est si facile d'obtenir de liaison ET les erreurs de validation.OriginalL'auteur Janning
Selon ce post https://blog.codecentric.de/en/2017/11/dynamic-validation-spring-boot-validation/ - vous pouvez ajouter un paramètre supplémentaire "Erreurs" de votre méthode de contrôleur - eg.
pour ensuite obtenir des erreurs de validation, le cas échéant, dans que.
OriginalL'auteur anders.norgaard