Spring MVC + Hibernate: les données des stratégies de validation
Nous le savons tous, Spring MVC, s'intègrent bien avec Hibernate Validator et de la JSR-303 en général. Mais Hibernate Validator, comme quelqu'un l'a dit, est quelque chose de Bean Validation uniquement, ce qui signifie que de plus en plus complexe des validations doit être poussé à la couche de données. Des exemples de telles validations: entreprise clé de l'unicité, de l'intra-dossiers de dépendance (ce qui est généralement quelque chose de pointer les DB des problèmes de conception, mais nous vivons dans un monde imparfait). Même de simples validations comme chaîne de caractères de longueur peut être déterminé par une valeur en DB, ce qui rend Hibernate Validator inutilisable.
Donc ma question est, est-il quelque chose de Printemps ou mise en veille prolongée ou JSR vous propose d'effectuer des complexes telles validations? Est-il un établi motif ou la pièce de technologie pour effectuer une telle validation dans un Contrôleur standard-Service-Référentiel de configuration basé sur Spring et Hibernate?
Mise à JOUR: Permettez-moi d'être plus précis. Par exemple, il y a un formulaire qui envoie une requête AJAX enregistrer la demande au contrôleur de save
méthode. Si certains d'erreur de validation de produit, simple ou "complexe", nous devrions revenir au navigateur avec quelques json indiquant un champ problématique et d'erreur associé. Pour de simples erreurs que je peux extraire le champ (le cas échéant) et le message d'erreur de BindingResult
. Quelles sont les infrastructures (peut-être, et non pas ad-hoc des exceptions?) voulez-vous proposer pour le "complexe" des erreurs? À l'aide de gestionnaire d'exception ne semble pas être une bonne idée pour moi, parce que la séparation même processus de validation entre save
méthode et @ExceptionHandler
rend les choses complexes. Actuellement j'utilise ad-hoc exception (comme, ValidationException
):
public @ResponseBody Result save(@Valid Entity entity, BindingResult errors) {
Result r = new Result();
if (errors.hasErrors()) {
r.setStatus(Result.VALIDATION_ERROR);
//...
} else {
try {
dao.save(entity);
r.setStatus(Result.SUCCESS);
} except (ValidationException e) {
r.setStatus(Result.VALIDATION_ERROR);
r.setText(e.getMessage());
}
}
return r;
}
Peut vous offrir encore plus optimale approche?
Vous devez vous connecter pour publier un commentaire.
Oui, il y a le bon vieux établi Java motif de Exception jeter.
Spring MVC intègre assez bien (pour des exemples de code, vous pouvez directement passer à la deuxième partie de ma réponse).
Ce que vous appelez "complexe validations" sont en fait des exceptions : les clés d'entreprise unicité d'erreur, une faible couche de bases de données ou des erreurs, etc.
Rappel : qu'est-ce que la validation de Spring MVC ?
De Validation devraient arriver sur la couche de présentation. C'est essentiellement sur la validation de formulaire soumis champs.
On pourrait les classer en deux types :
1) la Lumière de validation (avec la JSR-303/Hibernate validation) : vérifier la présence d'un soumis champ a une donnée
@Size
/@Length
, qu'il est@NotNull
ou@NotEmpty
/@NotBlank
, en vérifiant qu'il a un@Email
format, etc.2) Lourd de validation, ou complexes de validation sont plus au sujet de cas particuliers, des validations de champ, telles que le cross-validation de champ :
fieldA
,fieldB
etfieldC
. Individuellement, chaque champ peut être vide, mais au moins l'un d'entre eux ne doit pas être vide.userAge
champ a une valeur de moins de 18 ans,responsibleUser
champ ne doit pas être null etresponsibleUser
s'âge doit être de plus de 21 ans.Ces validations peuvent être mises en œuvre avec Le printemps du programme de validation des implémentations, ou personnalisé annotations/contraintes.
Maintenant, je comprends qu'avec tous ces la validation des équipements, en plus du fait que le Printemps n'est pas intrusive et vous permet de faire tout ce que vous voulez (pour le meilleur ou pour le pire), on peut être tenté d'utiliser la "validation marteau" pour quelque chose de vaguement liées à la gestion des erreurs.
Et cela fonctionne : avec uniquement la validation, vous vérifiez chaque problème possible dans votre validateurs/annotations (et pas la jeter aucune exception dans les couches inférieures). Il est mauvais, parce que vous priez, que vous avez pensé à tous les cas. Vous n'avez pas tirer parti de Java exceptions qui vous permettra de simplifier votre logique et de réduire la probabilité de faire une erreur en oubliant de vérifier que quelque chose avait une erreur.
Donc dans le Spring MVC monde, on ne doit pas l'erreur de validation (c'est-à-dire, de l'INTERFACE utilisateur de validation) pour la couche inférieure de la exceptions, tel est le Service des exceptions ou DB exceptions (clé d'unicité, etc.).
Comment gérer les exceptions dans Spring MVC dans une façon pratique ?
Certaines personnes de penser "Oh dieu, donc dans mon contrôleur je dois vérifier tous les possibles exceptions, un par un, et de réfléchir à un message d'erreur pour chacun d'eux ? C'EST PAS POSSIBLE !". Je suis une de ces personnes. 🙂
Pour la plupart des cas, il suffit d'utiliser certains génériques vérifié classe d'exception que tous vos exceptions s'étendre. Puis il suffit de le gérer dans votre contrôleur Spring MVC avec @ExceptionHandler et un message d'erreur générique.
Exemple de Code :
et
Simple, rapide, facile et propre !
Pour les moments où vous avez besoin d'afficher des messages d'erreur pour certaines exceptions spécifiques, ou lorsque vous ne pouvez pas avoir un generic top-level exception en raison d'une mauvaise conception du système d'héritage vous ne pouvez pas modifier, il suffit d'ajouter d'autres
@ExceptionHandler
s.Une autre astuce : pour moins encombré de code, vous pouvez traiter plusieurs exceptions avec
Ligne du bas : lors de l'utilisation de la validation ? quand utiliser des exceptions ?
Quand je dis "les Erreurs de l'INTERFACE utilisateur", je veux dire "l'utilisateur a entré quelque chose de mal dans sa forme".
Références :
@NotNull
case toujours il nécessite un traitement complexe comme DB frappé. Où placeriez-vous cette case? Si dans@ExceptionHandler
alors je ne comprends pas pourquoi les séparer de laBindingResult
vérifier. Un développeur pourrait s'attendre à trouver toutes les étapes de validation regroupés (ou au moins enchaînés) ensemble. De les mettre dans des méthodes distinctes demanderait de l'effort mental si le contrôleur est grand (comme, "où est-ce que le message de validation viennent?! pas de BindingResult!").