1. Vérification des paramètres
En développement, vous devez souvent rédiger du code pour la vérification du champ, tels que les champs non vides, les limites de longueur du champ, la vérification du format des boîtes aux lettres, etc. Je pense personnellement qu'il y a deux problèmes lors de la rédaction de ces codes qui ont peu à voir avec la logique commerciale:
Le validateur Hibernate (document officiel) fournit une méthode d'implémentation de vérification relativement complète et pratique.
Le package Spring-Boot-Starter-Web a le package Hibernate-validator, et il n'est pas nécessaire de se référer à la dépendance du validateur Hibernate.
2. Démo de vérification du validateur hibernate
Regardons d'abord une simple démo, ajoutant l'annotation du validateur:
import org.hibernate.validator.constraints.notblank; import javax.validation.constraints.assertfalse; import javax.validation.constraints.pattern;
@ Getter @ seter @ noargsconstructorpublic classe Demomodel {@notblank (message = "Le nom d'utilisateur ne peut pas être vide") Nom d'utilisateur de chaîne privé; @Notblank (message = "Age ne peut pas être vide") @Pattern (regexp = "^ [0-9] {1,2} $", message = "Age incorrect") Private String Age; @Assertfalse (message = "doit être faux") Boolean privé isfalse; / ** * S'il est vide, il ne sera pas vérifié, et s'il n'est pas vide, il sera vérifié * / @pattern (regexp = "^ [0-9] {4} - [0-9] {2} - [0-9] {2} $", message = "La date de naissance est incorrect") anniversaire de chaîne privée;};Vérification post-interface, BindingResult est une collection de résultats qui ne parviennent pas à passer la vérification:
@RequestMapping ("/ Demo2") public void Demo2 (@Requestbody @valid Demomodel Demo, BindingResult Result) {if (result.haserrors ()) {for (Objectror Error: result.getAllerror ()) {System.out.println (error.getDefaultMessage ()); }}} Paramètres transmis par la demande post :{"userName":"dd","age":120,"isFalse":true,"birthday":"21010-21-12"}
Résultat de sortie:
La date de naissance est incorrecte et doit être fausse
Âge incorrect
La vérification des paramètres est très pratique. Si la vérification Annotation + sur le terrain n'est pas transmise, elle peut remplacer l'écriture de nombreux codes de vérification de restriction non vides et de champ. Ci-dessous, nous avons une compréhension plus approfondie de la façon de jouer la vérification des paramètres.
3. Mode de vérification d'hibernate
Les lecteurs prudents doivent avoir découvert que dans l'exemple ci-dessus, tous les ensembles qui ne parviennent pas à passer la vérification sont renvoyés immédiatement. Habituellement, lorsque le premier champ ne répond pas aux exigences de vérification en ordre, la demande peut être rejetée directement. Le validateur Hibernate a les deux modes de vérification suivants:
1. Mode normal (ce mode est par défaut)
Mode normal (tous les attributs seront vérifiés, puis toutes les informations de défaillance de vérification seront renvoyées)
2. Échec rapide de revenir en mode
Mode de retour rapide de défaillance (retour tant qu'il y a une défaillance de vérification)
Deux méthodes de configuration du mode de vérification: (reportez-vous à la documentation officielle)
FailFast: True Fast Fail Return Mode False False Normal Mode
ValidatorFactory ValidatorFactory = Validation.ByProvider (HiberNateValidator.Class) .Configure () .Failfast (true) .BuildValidatorFactory (); Validator validator = validatorfactory.getValidator ();
et (hibernate.validator.fail_fast: le mode de rendement rapide de l'échec rapide faux mode normal)
ValidatorFactory ValidatorFactory = Validation.ByProvider (HiberNateValidator.class) .Configure () .AddProperty ("HiberNate.Validator.fail_fast", "true") .buildValidatorFactory (); Validator validator = validatorfactory.getValidator ();4. Deux types de vérifications d'hibernate
Configurez le validateur Hibernate en mode retour à une défaillance rapide:
@ConfigurationPublic Class ValidatorConfiguration {@Bean public Validator Validator () {ValidatorFactory ValidatorFactory = Validation.ByProvider (HiberNateValidator.class) .Configure () .AddProperty ("Hibernatfate.Validator.fail_fast", "true") .buildvalidatorfactory (); Validator validator = validatorfactory.getValidator (); validateur de retour; }}1. Demande la vérification du paramètre
Comme dans l'exemple de la démo, lors de la vérification des paramètres de demande, ajoutez @valid entre la démo Demomodel @Requestbody, puis ajoutez BindInSult; Pour plusieurs paramètres, vous pouvez ajouter plusieurs @Valid et BindingResult, tels que:
public void test () (@ requestbody @valid Demomodel Demo, lisingResult Result) public void test () (@ requestbody @valid Demomodel Demo, ResultResult Result, @ requestbody @valid Demomodel Demo2, BindingResult Result2)
@RequestMapping ("/ Demo2") public void Demo2 (@Requestbody @valid Demomodel Demo, BindingResult Result) {if (result.haserrors ()) {for (Objectror Error: result.getAllerror ()) {System.out.println (error.getDefaultMessage ()); }}}2. Obtenez la vérification des paramètres (@RequestParam Vérification des paramètres)
En utilisant la méthode de vérification des haricots, il n'y a aucun moyen de vérifier le contenu de RequestParam. Généralement, lorsque le traitement des demandes de l'obtention (ou moins de paramètres), le code suivant sera utilisé:
@RequestMapping (value = "/ demo3", méthode = requestMethod.get) public void Demo3 (@RequestParam (name = "grade", requis = true) int grade, @ requestParam (name = "classe", "+ classe); }
L'utilisation de l'annotation @valid pour annoter les paramètres correspondant à RequestParam n'est pas valide. L'annotation @validated est nécessaire pour que la vérification prenne effet. Comme indiqué ci-dessous:
un. À l'heure actuelle, vous devez utiliser le bean de MethodValidationPostProcessor :
@Bean Public MethodValidationPostProcessor MethodValidationPostProcessor () {/ ** La défaut est le mode normal, et toutes les vérifications seront renvoyées sans transmettre la collection d'informations * / return new MethodValidationPostProcessor (); } Ou vous pouvez définir le validateur pour MethodValidationPostProcessor (car le validateur n'est pas utilisé pour la vérification pour le moment, la configuration du validateur ne fonctionne pas)
@Bean Public MethodValidationPostProcessor MethodValidationPostProcessor () {MethodValidationPostProcessor PostProcessor = new MethodoValidationPostProcessor (); / ** définir le mode validateur sur un retour rapide * / postprocess.setValidator (validator ()); Retour postprocesseur; } @Bean public validator validator () {validatorfactory validatorfactory = validation.byprovider (hibernatevalidator.class) .configure () .adddproperty ("hibernate.validator.fail_fast", "true") .buildvalidatorfactory (); Validator validator = validatorfactory.getValidator (); validateur de retour; }né Ajouter une annotation au contrôleur où se trouve la méthode @Validated
@RequestMapping ("/ validation") @ restController @ validedaPublic Class validationController {/ ** S'il n'y a que quelques objets, écrivez simplement les paramètres sur la couche de contrôleur, puis vérifiez-les dans la couche de contrôleur. * / @RequestMapping (value = "/ demo3", méthode = requestMethod.get) public void Demo3 (@Range (min = 1, max = 9, message = "Grade ne peut être que de 1 à 9") @RequestParam (name = "grade", requis = true) int, @Min (valeur = 1, message = "classe minimum peut seulement être 1") @max (value = "MAXIMUM MAIXUM CANUMUME ÊTRE UN 99 ") @RequestParam (name =" classe ", obligatoire = true) int classe) {System.out.println (grade +", "+ classe); }}c. Retourner à l'invite d'informations de vérification
Vous pouvez voir: lorsque la vérification échoue, une exception CONSTRAINTVIOLATIONException est lancée et la même exception de capture est manipulée:
@ ControllerAdvice @ ComponentPublic Class GlobalexceptionHandler {@ExceptionHandler @ResponseBody @ResponSestatus (httpstatus.bad_request) Public String Handle (ValidationException Exception) {if (exception instance of contrainvioLationException) {ConstraintvioLationException exs = (exception instanceException) exception; Set <CONSTRAINTVIOLATION <? >> VIOLATIONS = exs.getConstraintviolations (); pour (CONSTRAINTVIOLATION <?> Élément: Violations) {/ ** Imprimez les informations qui ne parviennent pas à passer la vérification * / System.out.println (item.getMessage ()); }} renvoie "Bad Request";; }}d. Vérification
Adresse de demande de service du navigateur: http: // localhost: 8080 / validation / Demo3? Grade = 18 & Classroom = 888
Les informations de sortie lorsque la méthodeValidationPostProcessor est retournée sans configurer la défaillance rapide est la suivante:
Les notes ne peuvent être que de 1 à 9
La classe maximale ne peut être que 99
Lorsque la méthodeValidationPostProcessor est configurée avec le retour de défaillance rapide, les informations de sortie sont les suivantes:
Les notes ne peuvent être que de 1 à 9
Adresse de la demande de service du navigateur: http: // localhost: 8080 / validation / demo3? Grade = 0 & classroom = 0
Les informations de sortie lorsque la méthodeValidationPostProcessor est retournée sans configurer la défaillance rapide est la suivante:
Les notes ne peuvent être que de 1 à 9
La classe minimale ne peut être que 1
Lorsque la méthodeValidationPostProcessor est configurée avec le retour de défaillance rapide, les informations de sortie sont les suivantes:
Les notes ne peuvent être que de 1 à 9
3. Vérification du modèle
Modèle à vérifier:
@Datapublic class Demo2 {@Length (min = 5, max = 17, message = "longueur de longueur se situe entre [5,17]") Longueur de chaîne privée; / ** @ size ne peut pas vérifier entier, adapté à la chaîne, à la collecte, à la carte et aux tableaux * / @size (min = 1, max = 3, message = "taille entre [1,3]") l'âge de chaîne privée; @Range (min = 150, max = 250, message = "plage se situe entre [150,250]") private int high; @Size (min = 3, max = 5, message = "La taille de la liste est dans [3,5]") Liste privée <string> liste;}Vérifiez le modèle, toutes les vérifications suivantes sont passées:
@Autowired Private Validator Validator; @RequestMapping ("/ Demo3") public void Demo3 () {Demo2 Demo2 = new Demo2 (); Demo2.Setage ("111"); Demo2.Sethigh (150); Demo2.SetLength ("ABCDE"); DEMO2.SetList (new ArrayList <string> () {{add ("111"); add ("222"); add ("333");}}); SET <CONSTRAINTVIOLATION <MO2 >> VIOLATIONSET = VALIDATOR.VALIDAD (DEMO2); pour (CONSTRAINTVIOLATION <Demo2> Modèle: violationNet) {System.out.println (Model.getMessage ()); }}4. Vérification de la cascade des objets
L'objet contient un autre objet en tant que propriété et ajouter @valid à la propriété pour vérifier la vérification à l'intérieur de l'objet en tant que propriété: (Lors de la vérification de l'exemple Demo2, vous pouvez vérifier les champs de Demo2)
@Datapublic Class Demo2 {@Size (min = 3, max = 5, message = "La taille de la liste est dans [3,5]") Liste privée <string>; @Notnull @valid private Demo3 Demo3;} @ Datapublic Class Demo3 {@Length (min = 5, max = 17, message = "longueur de longueur est entre [5,17]") String privé Extfield;}Vérification en cascade:
/ ** bean est configuré avec une défaillance rapide Retour Bean * / @Autowired Private Validator Validator; @RequestMapping ("/ Demo3") public void Demo3 () {Demo2 Demo2 = new Demo2 (); DEMO2.SetList (new ArrayList <string> () {{add ("111"); add ("222"); add ("333");}}); Demo3 Demo3 = new Demo3 (); Demo3.SeTextField ("22"); Demo2.SetDemo3 (Demo3); SET <CONSTRAINTVIOLATION <MO2 >> VIOLATIONSET = VALIDATOR.VALIDAD (DEMO2); pour (CONSTRAINTVIOLATION <Demo2> Modèle: violationNet) {System.out.println (Model.getMessage ()); }}Le champ Extfield de Demo3 peut être vérifié.
5. Vérification du groupe
Conclusion: Lors de la vérification de la séquence de regroupement, vérifiez-la dans l'ordre de regroupement spécifié. Si la vérification précédente échoue, le regroupement ultérieur ne peut pas être vérifié.
Il existe un scénario où lorsque de nouvelles informations utilisateur sont ajoutées, il n'est pas nécessaire de vérifier l'utilisateur (car le système est généré); Lors de la modification, l'utilisateur doit vérifier l'utilisateur et la fonction de vérification de groupe de l'utilisateur au validateur peut être utilisée.
Définissez le validateur sur le mode de vérification normal ("hibernate.validator.fail_fast", "false") et utilisez la vérification groupa, groupB et modèle:
Groupa, groupB: interface publique groupa {} interface publique GroupB {}Vérifier le modèle: personne
@Datapublic class Person {@notblank @Range (min = 1, max = Integer.max_value, message = "doit être supérieur à 0", groupes = {groupa.class}) / ** ID utilisateur * / private Integer userId; @Notblank @Length (min = 4, max = 20, message = "doit être dans [4,20]", groupes = {groupB.class}) / ** nom d'utilisateur * / nom d'utilisateur de chaîne privée; @Notblank @Range (min = 0, max = 100, message = "L'âge doit être à [0,100]", groupes = {default.class}) / ** Âge * / private Integer Age; @Range (min = 0, max = 2, message = "Le genre doit être à [0,2]", groupes = {groupB.class}) / ** Sexe 0: inconnu; 1: Homme; 2: Femme * / Sexe entier privé;}Comme le montre la personne ci-dessus, les trois groupes sont respectivement validés comme suit:
un. Regroupement
Seuls les groupes de balises GroupA et GroupB sont vérifiés:
@RequestMapping ("/ Demo5") public void Demo5 () {Person p = new Person (); / ** La vérification GroupA ne passe pas * / p.seTUserid (-12); / ** Groupa Verification Pass * / //p.SetUserId(12); P.SetUsername ("A"); P.Setage (110); P.SetSEX (5); Set <contraintViolation <ponge>> validate = validator.validate (p, groupa.class, groupB.class); pour (CONSTRAINTVIOLATION <SOND> ITEM: valider) {System.out.println (élément); }}ou
@RequestMapping ("/ Demo6") public void Demo6 (@Validated ({groupa.class, groupB.class}) Person p, bindingResult Result) {if (result.haserrors ()) {list <objecterror> allerrors = result.getAllERROR (); pour (objectorror error: allerrors) {System.out.println (erreur); }}}Si GroupA, GroupB et Default ne sont pas validés:
Les informations de vérification sont les suivantes:
CONSTRAINTVIOLATIONIMPL {InterpolatedMessage = 'Doit être dans [4,20]', PropertyPath = Username, rootBlass = class validator.demo.project.model.person, Messagetemplate = 'doit être dans [4,20]'} contraintvioLationImpl {interpolatedmesage = 'doit être plus important que 0', propertypath = userId, interpolatedmesage = ' rootBeANClass = class validator.demo.project.model.person, MessageTemplate = 'doit être supérieur à 0'} CONSTRAINTVIOLATIONIMPL {InterpolatedMessage = 'Gender doit être dans [0,2]', PropertyPath = Sex, rootBeANClass = Class Validator.demo.project.Model. [0,2] '}Si la vérification groupa est passée, GroupB et la vérification par défaut n'est pas transmise:
Les informations de vérification sont les suivantes:
CONSTRAINTVIOLATIONIMPL {InterpolatedMessage = 'Doit être dans [4,20]', PropertyPath = Username, rootBlass = class validator.demo.project.model.person, Messagetemplate = 'doit être dans [4,20]'} CONSTRAINTvioLationImpl {interpolatedMessage = 'Gender doit être dans [0 rootBeANClass = class validator.demo.project.model.person, messageTemplate = 'Le genre doit être dans [0,2]'}né Séquence de groupe
En plus de spécifier s'il faut vérifier par groupe, vous pouvez également spécifier l'ordre de vérification du groupe. Si la vérification du groupe précédent échoue, la vérification du groupe suivant ne sera pas effectuée:
Séquence du groupe spécifié (groupa》 GroupB》 par défaut):
@GroupSequence ({groupa.class, groupb.class, default.class}) Interface publique GroupOrder {}Démo de test:
@RequestMapping ("/ Demo7") public void Demo7 () {Person p = new Person (); / ** La vérification GroupA ne passe pas * / //p.seserUserrid(-12); / ** Groupa Verification Pass * / P.SetUserrid (12); P.SetUsername ("A"); P.Setage (110); P.SetSEX (5); Set <contraintviolation <pony>> valider = validator.validate (p, groupOrder.class); pour (CONSTRAINTVIOLATION <SOND> ITEM: valider) {System.out.println (élément); }}ou
@RequestMapping ("/ Demo8") public void Demo8 (@Validated ({groupOrder.class}) Person P, ResultResult Result) {if (result.haserrors ()) {list <obJecterror> allerRorrs = result.getAllErrors (); pour (objectorror error: allerrors) {System.out.println (erreur); }}}Si GroupA, GroupB et Default ne sont pas validés:
Les informations de vérification sont les suivantes:
CONSTRAINTVIOLATIONIMPL {InterpolatedMessage = 'Doit être supérieur à 0', PropertyPath = UserId, rootBeANClass = class validator.demo.project.model.eson, MessageTemplate = 'doit être supérieur à 0'}Si la vérification groupa est passée, GroupB et la vérification par défaut n'est pas transmise:
Les informations de vérification sont les suivantes:
CONSTRAINTVIOLATIONIMPL {InterpolatedMessage = 'Doit être dans [4,20]', PropertyPath = Username, rootBlass = class validator.demo.project.model.person, Messagetemplate = 'doit être dans [4,20]'} CONSTRAINTvioLationImpl {interpolatedMessage = 'Gender doit être dans [0 rootBeANClass = class validator.demo.project.model.person, messageTemplate = 'Le genre doit être dans [0,2]'}Conclusion: Lors de la vérification de la séquence de regroupement, vérifiez-la dans l'ordre de regroupement spécifié. Si la vérification précédente échoue, le regroupement ultérieur ne peut pas être vérifié.
5. Vérificateur personnalisé
D'une manière générale, la vérification personnalisée peut résoudre de nombreux problèmes. Mais il y a aussi des moments où la situation ne peut pas être remplie. Pour le moment, nous pouvons implémenter l'interface validatrice et personnaliser le validateur dont nous avons besoin.
Comme indiqué ci-dessous, un validateur de cas personnalisé est implémenté:
Public Enum Casemode {Upper, inférieur;} @ cible ({elementType.Method, elementType.field, elementType.annotation_type}) @ rétention (RetenderPolicy.Runtime) @Constraint (validedBy = CheckCaseValidator.class) @DocumentEdPublic @Interface Checkcase {String Message () () "; Classe <?> [] Groupes () default {}; Classe <? étend la charge utile> [] Payload () par défaut {}; CaseMode Value ();} Classe publique CheckCaseValidator implémente CONSTRAINTVALIDATOR <CHECKCASE, STRING> {private CaseMode CaseMode; public void initialize (checkCase checkCase) {this.casemode = checkcase.value (); } public boolean isvalid (String S, CONSTRAINTVALIDATORCONT CONSTRAINTVALIDATORCEXT) {if (s == null) {return true; } if (casemode == CaseMode.upper) {return s.equals (s.touppercase ()); } else {return s.equals (s.tolowercase ()); }}}Modèle à vérifier:
Demo de classe publique {@CheckCase (value = casemode.lower, message = "nom d'utilisateur doit être minuscule") Nom d'utilisateur de chaîne privée; public String getUserName () {return username; } public void setUsername (String username) {this.userName = username; }}Configuration du validateur:
@Bean public validator validator () {validatorfactory validatorfactory = validation.byprovider (hibernatevalidator.class) .configure () .addproperty ("hibernate.validator.fail_fast", "true") .buildValidatorFactory (); Validator validator = validatorfactory.getValidator (); validateur de retour; }Test de vérification:
@RequestMapping ("/ Demo4") public void Demo4 () {Demo Demo = new Demo (); Demo.SetUsername ("nom d'utilisateur"); SET <CONSTRAINTVIOLATION <MO>> VALIDAD = VALIDATOR.VALIDAD (Demo); pour (CONSTRAINTVIOLATION <MO> Dem: valider) {System.out.println (dem.getMessage ()); }}Résultat de sortie:
Le nom d'utilisateur doit être en minuscules
6. Annotations communes
La contrainte intégrée dans la validation du bean @Null L'élément annoté doit être nul @notnull L'élément annoté ne doit pas être null @asserttrue L'élément annoté doit être vrai @assertfalse L'élément annoté doit être false @min (valeur) L'élément annoté doit être un nombre, sa valeur doit être supérieure à la valeur minimale spécifiée @max (valeur). À la valeur maximale spécifiée @decimalmin (valeur) L'élément annoté doit être un nombre, sa valeur doit être supérieure ou égale à la valeur minimale spécifiée @decimalmax (valeur) L'élément annoté doit être un nombre, sa valeur doit être inférieure ou égale à la valeur maximale spécifiée @Size (max =, min =) La taille de l'élément annotatisé doit être dans la plage spécifiée @Digits (Min =) La taille de la fraction annotée doit être dans la plage spécifiée @Digits (INFRAGE) Doit être un nombre et sa valeur doit être dans la plage acceptable @Past L'élément annoté doit être une date antérieure @future L'élément annoté doit être une date future @Pattern (regex =, Contrainte jointe @notblank (message =) La chaîne de vérification n'est pas nul et doit être plus grande que 0 @Email l'élément annotaté doit être le courrier @Length (min =, max =) La chaîne annotée doit être dans la plage spécifiée @Notempty La chaîne annotée doit être non vide @Range (min =, max =, message =) L'élément annoté doit être dans la plage appropriée // supérieure à 0,01, ne contenant pas 0,01 @ notnull @ deCilalmin (valeur = "0,01", y compris = false) private Integer; 0.01 @ notnull @ decimalmin (valeur = "0,01", y compris = true) private bigdecimal greatorequalthan; @Length (min = 1, max = 20, message = "message ne peut pas être vide") // ne peut pas utiliser la longueur comme plage // @ range (min = 1, max = 20, message = "message ne peut pas être vide") Message de chaîne privé;
7. Matériaux de référence
Références:
http://docs.jboss.org/hibernate/validator/4.2/reference/zh-cn/html_single/#validator-gettingstarted