Proljetna MVC prilagođena provjera valjanosti

1. Pregled

Općenito, kada moramo provjeriti valjanost korisničkog unosa, Spring MVC nudi standardne unaprijed definirane validatore.

Međutim, kada trebamo potvrditi određeniju vrstu unosa, imamo mogućnost stvaranja vlastite, prilagođene logike provjere valjanosti.

U ovom ćemo članku učiniti upravo to - stvorit ćemo prilagođeni validator za provjeru valjanosti obrasca s poljem telefonskog broja, a zatim prikazati prilagođeni validator za više polja.

Ovaj se članak usredotočuje na proljetni MVC. Naš članak Provjera valjanosti u proljetnom pokretanju opisuje kako napraviti prilagođene provjere valjanosti u proljetnom pokretanju.

2. Postavljanje

Da biste iskoristili API, dodajte ovisnost na svoj pom.xml datoteka:

 org.hibernate hibernate-validator 6.0.10.Finalni 

Najnoviju verziju ovisnosti možete provjeriti ovdje.

Ako koristimo Spring Boot, tada možemo dodati samo proljeće-boot-starter-web, koji će donijeti hibernacijski validator ovisnost također.

3. Prilagođena provjera valjanosti

Stvaranje prilagođenog programa za provjeru valjanosti podrazumijeva stavljanje vlastite bilješke i njezinu upotrebu u našem modelu za provođenje pravila provjere valjanosti.

Pa, kreirajmo svoje prilagođeni validator - koji provjerava brojeve telefona. Telefonski broj mora biti broj s više od osam znamenki, ali ne više od 11 znamenki.

4. Nova bilješka

Stvorimo novu @sučelje da definiramo našu napomenu:

@Documented @Constraint (validatedBy = ContactNumberValidator.class) @Target ({ElementType.METHOD, ElementType.FIELD}) @Retention (RetentionPolicy.RUNTIME) public @interface ContactNumberConstraint {String message () default "Nevažeći telefonski broj"; Class [] groups () zadani {}; Klasa [] korisni teret () zadana {}; }

Uz @Ograničenje napomena, definirali smo klasu koja će potvrditi naše polje, poruka() je poruka o pogrešci koja se prikazuje u korisničkom sučelju, a dodatni kôd je većina uzorka koji odgovara standardima Spring.

5. Izrada programa za provjeru valjanosti

Stvorimo sada klasu validatora koja provodi pravila naše provjere valjanosti:

javna klasa ContactNumberValidator implementira ConstraintValidator {@Override javnu prazninu inicijalizira (ContactNumberConstraint contactNumber) {} @Override javni boolean isValid (String contactField, ConstraintValidatorContext cxt) {return contactField! = null && contactField.matches (contactField.length ()> 8) && (contactField.length () <14); }}

Klasa provjere primjenjuje ConstraintValidator sučelje i mora implementirati isValid metoda; u ovoj smo metodi definirali naša pravila provjere valjanosti.

Naravno, ovdje idemo s jednostavnim pravilom provjere valjanosti kako bismo pokazali kako validator radi.

ConstraintValidator dusavršava logiku za provjeru valjanosti datog ograničenja za dati objekt. Provedbe moraju biti u skladu sa sljedećim ograničenjima:

  • objekt se mora razriješiti na neparametarizirani tip
  • generički parametri objekta moraju biti neograničeni zamjenski tipovi

6. Primjena napomene o provjeri valjanosti

U našem smo slučaju stvorili jednostavnu klasu s jednim poljem za primjenu pravila provjere valjanosti. Evo, postavljamo naše bilješko polje za provjeru:

@ContactNumberConstraint privatni String telefon;

Definirali smo polje niza i označili ga svojom prilagođenom bilješkom @ContactNumberConstraint. U našem kontroloru stvorili smo preslikavanja i obradili pogrešku ako postoji:

@Controller javna klasa ValidatedPhoneController {@GetMapping ("/ validatePhone") javni niz loadFormPage (Model m) {m.addAttribute ("validatedPhone", novi ValidatedPhone ()); vrati "phoneHome"; } @PostMapping ("/ addValidatePhone") javni niz submitForm (@Valid ValidatedPhone validatedPhone, BindingResult rezultat, Model m) {if (result.hasErrors ()) {return "phoneHome"; } m.addAttribute ("poruka", "Uspješno spremljen telefon:" + potvrđenPhone.toString ()); vrati "phoneHome"; }}

Definirali smo ovaj jednostavni kontroler koji ima jedan JSP stranicu i upotrijebite pošalji obrazac metoda za provođenje provjere valjanosti našeg telefonskog broja.

7. Pogled

Naš je pogled osnovna JSP stranica s obrascem koji ima jedno polje. Kada korisnik pošalje obrazac, tada naš prilagođeni validator provjerava polje i preusmjerava na istu stranicu s porukom uspješne ili neuspjele provjere valjanosti:

 Telefon: 

8. Ispitivanja

Ajmo sada testirati naš kontroler i provjeriti daje li nam odgovarajući odgovor i prikaz:

@Test javna praznina danaPhonePageUri_whenMockMvc_thenReturnsPhonePage () {this.mockMvc. izvesti (get ("/ validatePhone")). andExpect (view (). name ("phoneHome")); }

Također, provjerimo je li naše polje provjereno, na temelju korisničkog unosa:

@Test javna praznina zadanaPhoneURIWithPostAndFormData_whenMockMVC_thenVerifyErrorResponse () {this.mockMvc.perform (MockMvcRequestBuilders.post ("/ addValidatePhone"). Accept (MediaType.TEXT_HTML). Param ("phone" "input", parametar ("telefon")). andExpect (model (). attributeHasFieldErrorCode ("validatedPhone", "phone", "ContactNumberConstraint")). andExpect (view (). name ("phoneHome")). andExpect (status (). isOk ()). andDo (print ()); }

U testu pružamo korisniku unos "123" i - kao što smo i očekivali - sve funkcionira i vidimo grešku na strani klijenta.

9. Provjera valjanosti prilagođene razine razreda

Prilagođena bilješka za provjeru valjanosti također se može definirati na razini klase radi provjere valjanosti više od jednog atributa klase.

Uobičajeni slučaj upotrebe za ovaj scenarij je provjera imaju li dva polja klase odgovarajuće vrijednosti.

9.1. Izrada napomene

Dodajmo novu napomenu pod nazivom FieldsValueMatch koja se kasnije može primijeniti na razred. Napomena će imati dva parametra polje i fieldMatch koja predstavljaju imena polja za usporedbu:

@Constraint (validatedBy = FieldsValueMatchValidator.class) @Target ({ElementType.TYPE}) @Retention (RetentionPolicy.RUNTIME) public @interface FieldsValueMatch {String message () default "Vrijednosti polja se ne podudaraju!"; Polje niza (); String fieldMatch (); @Target ({ElementType.TYPE}) @Retention (RetentionPolicy.RUNTIME) @ Popis sučelja {FieldsValueMatch [] value (); }}

Vidimo da naša prilagođena bilješka također sadrži a Popis pod-sučelje za definiranje višestrukog FieldsValueMatch napomene na predavanju.

9.2. Izrada programa za provjeru valjanosti

Dalje, moramo dodati FieldsValueMatchValidator klasa koja će sadržavati stvarnu logiku provjere valjanosti:

javna klasa FieldsValueMatchValidator implementira ConstraintValidator {polje privatnog niza; private String fieldMatch; javna void inicijalizacija (FieldsValueMatch constraintAnnotation) {this.field = constraintAnnotation.field (); this.fieldMatch = constraintAnnotation.fieldMatch (); } public boolean isValid (vrijednost objekta, ConstraintValidatorContext context) {Object fieldValue = new BeanWrapperImpl (value) .getPropertyValue (field); Object fieldMatchValue = novi BeanWrapperImpl (vrijednost) .getPropertyValue (fieldMatch); if (fieldValue! = null) {return fieldValue.equals (fieldMatchValue); } else {return fieldMatchValue == null; }}}

The isValid () metoda dohvaća vrijednosti dva polja i provjerava jesu li jednake.

9.3. Primjena napomene

Stvorimo a NewUserForm klasa modela namijenjena podacima potrebnim za registraciju korisnika, koja ima dvije e-mail i zaporka atributa, zajedno s dva Potvrditi email i potvrdi lozinku atribute za ponovni unos dviju vrijednosti.

Budući da imamo dva polja za provjeru u odnosu na njihova odgovarajuća polja, dodajmo dva @FieldsValueMatch bilješke na NewUserForm razred, jedan za e-mail vrijednosti i jedan za zaporka vrijednosti:

@ FieldsValueMatch.List ({@FieldsValueMatch (field = "lozinka", fieldMatch = "verifyPassword", message = "Lozinke se ne podudaraju!"), @FieldsValueMatch (field = "email", fieldMatch = "verifyEmail", message = " Adrese e-pošte se ne podudaraju! ")}) Javna klasa NewUserForm {privatni niz e-pošte; privatni niz verifyEmail; privatna lozinka za niz; privatni niz verifyPassword; // standardni konstruktor, getteri, postavljači}

Da bismo provjerili valjanost modela u Spring MVC, stvorimo kontroler s /korisnik POST mapiranje koje prima a NewUserForm objekt označen s @Valid i provjerava postoje li pogreške u provjeri:

@Controller javna klasa NewUserController {@GetMapping ("/ user") javni niz loadFormPage (model modela) {model.addAttribute ("newUserForm", new NewUserForm ()); vratiti "userHome"; } @PostMapping ("/ user") javni niz submitForm (@Valid NewUserForm newUserForm, rezultat BindingResult, model modela) {if (result.hasErrors ()) {return "userHome"; } model.addAttribute ("poruka", "Važeći obrazac"); vratiti "userHome"; }}

9.4. Testiranje napomene

Da bismo provjerili našu prilagođenu bilješku na razini klase, napišite a JUNIT test koji šalje odgovarajuće informacije na /korisnik krajnja točka, a zatim provjerava da odgovor ne sadrži pogreške:

javna klasa ClassValidationMvcTest {private MockMvc mockMvc; @Prije javne void setup () {this.mockMvc = MockMvcBuilders .standaloneSetup (new NewUserController ()). Build (); } @Test javna praznina givenMatchingEmailPassword_whenPostNewUserForm_thenOk () baca izuzetak {this.mockMvc.perform (MockMvcRequestBuilders .post ("/ user") .accept (MediaType.TEXT_HTML). .Param ("email", "email zaštićen]"). ("verifyEmail", "[email protected]") .param ("password", "pass") .param ("verifyPassword", "pass")) .andExpect (model (). errorCount (0)) .andExpect ( status (). isOk ()); }}

Dalje, dodajmo i a JUNIT test koji šalje nepodudarajuće informacije na /korisnik krajnju točku i ustvrdite da će rezultat sadržavati dvije pogreške:

@Test public void givenNotMatchingEmailPassword_whenPostNewUserForm_thenOk () baca izuzetak {this.mockMvc.perform (MockMvcRequestBuilders .post ("/ user") .accept (MediaType.TEXT_HTML) .param ("email", "[zaštićena e-pošta]"). verifyEmail "," [email protected] ") .param (" password "," pass ") .param (" verifyPassword "," passsss ")) .andExpect (model (). errorCount (2)) .andExpect (status ( ) .isOk ()); }

10. Sažetak

U ovom smo kratkom članku pokazali kako stvoriti prilagođene validatore za provjeru polja ili klase i spajanje u Spring MVC.

Kao i uvijek, kôd iz članka možete pronaći na Githubu.