Existe-t-il une implémentation (ou une implémentation tierce pour) de la validation entre champs dans Hibernate Validator 4.x? Sinon, quelle est la façon la plus propre de mettre en œuvre un validateur de champ croisé?
Par exemple, comment pouvez-vous utiliser l'API pour valider deux propriétés de bean sont égales (comme la validation d'un champ de mot de passe correspond au champ de vérification de mot de passe).
Dans les annotations, je m'attendrais à quelque chose comme:
public class MyBean {
@Size(min=6, max=50)
private String pass;
@Equals(property="pass")
private String passVerify;
}
Réponses:
Chaque contrainte de champ doit être gérée par une annotation de validateur distincte, ou en d'autres termes, il n'est pas recommandé de vérifier l'annotation de validation d'un champ par rapport à d'autres champs; la validation entre champs doit être effectuée au niveau de la classe. De plus, la méthode préférée JSR-303 Section 2.2 pour exprimer plusieurs validations du même type est via une liste d'annotations. Cela permet au message d'erreur d'être spécifié par correspondance.
Par exemple, valider un formulaire commun:
L'annotation:
Le validateur:
la source
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()).addNode(secondFieldName).addConstraintViolation().disableDefaultConstraintViolation();
Donne la possibilité de mettre en évidence le bon champ (si seulement JSF le soutenait).BeanUtils.getProperty
renvoie une chaîne. L'exemple visait probablement à utiliserPropertyUtils.getProperty
ce qui renvoie un objet.Je vous propose une autre solution possible. Peut-être moins élégant, mais plus facile!
La
isValid
méthode est invoquée automatiquement par le validateur.la source
@AssertTrue
méthodes de ce type? Une convention de dénomination est valable?Je suis surpris que ce ne soit pas prêt à l'emploi. Quoi qu'il en soit, voici une solution possible.
J'ai créé un validateur de niveau classe, pas le niveau de champ comme décrit dans la question d'origine.
Voici le code d'annotation:
Et le validateur lui-même:
Notez que j'ai utilisé MVEL pour inspecter les propriétés de l'objet en cours de validation. Cela pourrait être remplacé par les API de réflexion standard ou s'il s'agit d'une classe spécifique que vous validez, les méthodes d'accesseur elles-mêmes.
L'annotation @Matches peut ensuite être utilisée sur un bean comme suit:
Comme avertissement, j'ai écrit cela au cours des 5 dernières minutes, donc je n'ai probablement pas encore résolu tous les bugs. Je mettrai à jour la réponse en cas de problème.
la source
Avec Hibernate Validator 4.1.0.Final, je recommande d'utiliser @ScriptAssert . Exceprt de sa JavaDoc:
Remarque: l'évaluation est effectuée par un " moteur " de script s'exécutant dans la machine virtuelle Java, donc côté Java "côté serveur", et non pas "côté client" comme indiqué dans certains commentaires.
Exemple:
ou avec un alias plus court et null-safe:
ou avec Java 7+ null-safe
Objects.equals()
:Néanmoins, il n'y a rien de mal avec une solution @Matches de validateur de niveau de classe personnalisé .
la source
Les validations entre champs peuvent être effectuées en créant des contraintes personnalisées.
Exemple: - Comparez les champs mot de passe et confirmPassword de l'instance utilisateur.
CompareStrings
StringComparisonMode
CompareStringsValidator
ConstraintValidatorHelper
Utilisateur
Tester
Production
Message:- [Password, ConfirmPassword] must be equal.
En utilisant la contrainte de validation CompareStrings, nous pouvons également comparer plus de deux propriétés et nous pouvons mélanger l'une des quatre méthodes de comparaison de chaînes.
ColorChoice
Tester
Production
Message:- Please choose three different colors.
De même, nous pouvons avoir des contraintes de validation inter-champs CompareNumbers, CompareDates, etc.
PS Je n'ai pas testé ce code dans un environnement de production (bien que je l'ai testé dans un environnement de développement), alors considérez ce code comme une version Milestone. Si vous trouvez un bug, merci d'écrire un joli commentaire. :)
la source
J'ai essayé l'exemple d'Alberthoven (hibernate-validator 4.0.2.GA) et j'obtiens une ValidationException: „Les méthodes annotées doivent suivre la convention de nommage JavaBeans. match () ne fonctionne pas ". Après avoir renommé la méthode de «match» en «isValid», cela fonctionne.
la source
Si vous utilisez Spring Framework, vous pouvez utiliser le Spring Expression Language (SpEL) pour cela. J'ai écrit une petite bibliothèque qui fournit un validateur JSR-303 basé sur SpEL - cela rend les validations inter-champs un jeu d'enfant! Jetez un œil à https://github.com/jirutka/validator-spring .
Cela validera la longueur et l'égalité des champs de mot de passe.
Vous pouvez également le modifier facilement pour valider les champs de mot de passe uniquement lorsqu'ils ne sont pas tous les deux vides.
la source
J'aime l'idée de Jakub Jirutka d'utiliser Spring Expression Language. Si vous ne souhaitez pas ajouter une autre bibliothèque / dépendance (en supposant que vous utilisez déjà Spring), voici une implémentation simplifiée de son idée.
La contrainte:
Le validateur:
Appliquer comme ceci:
la source
Je n'ai pas la réputation de commenter la première réponse, mais je voulais ajouter que j'ai ajouté des tests unitaires pour la réponse gagnante et que j'ai les observations suivantes:
la source
Très belle solution bradhouse. Existe-t-il un moyen d'appliquer l'annotation @Matches à plusieurs champs?
EDIT: Voici la solution que j'ai trouvée pour répondre à cette question, j'ai modifié la contrainte pour accepter un tableau au lieu d'une seule valeur:
Le code de l'annotation:
Et la mise en œuvre:
la source
Vous devez l'appeler explicitement. Dans l'exemple ci-dessus, bradhouse vous a donné toutes les étapes pour écrire une contrainte personnalisée.
Ajoutez ce code dans votre classe d'appelant.
dans le cas ci-dessus, il serait
la source
Pourquoi ne pas essayer Oval: http://oval.sourceforge.net/
On dirait qu'il prend en charge OGNL alors peut-être que vous pourriez le faire de manière plus naturelle
la source
Vous êtes géniaux les gars. Des idées vraiment incroyables. J'aime le plus Alberthoven et McGin , j'ai donc décidé de combiner les deux idées. Et développer une solution générique pour répondre à tous les cas. Voici ma solution proposée.
la source
J'ai fait une petite adaptation dans la solution de Nicko pour qu'il ne soit pas nécessaire d'utiliser la bibliothèque Apache Commons BeanUtils et de la remplacer par la solution déjà disponible au printemps, pour ceux qui l'utilisent car je peux être plus simple:
la source
Solution réalisée avec une question: comment accéder à un champ qui est décrit dans la propriété d'annotation
Et comment l'utiliser ...? Comme ça:
la source