Vår MVC tilpasset validering

1. Oversikt

Når vi trenger å validere brukerinngang, tilbyr Spring MVC vanligvis standard forhåndsdefinerte validatorer.

Når vi imidlertid trenger å validere en mer spesifikk type input, vi har muligheten til å lage vår egen, tilpassede valideringslogikk.

I denne artikkelen vil vi gjøre nettopp det - vi oppretter en tilpasset validator for å validere et skjema med et telefonnummerfelt, og viser deretter en tilpasset validator for flere felt.

Denne artikkelen fokuserer på Spring MVC. Vår artikkel Validering i Spring Boot beskriver hvordan du gjør tilpassede valideringer i Spring Boot.

2. Oppsett

For å dra nytte av API-et, legg til avhengigheten til din pom.xml fil:

 org.hibernate hibernate-validator 6.0.10.Final 

Den siste versjonen av avhengigheten kan sjekkes her.

Hvis vi bruker Spring Boot, kan vi bare legge til spring-boot-starter-web, som vil bringe inn dvalemodus avhengighet også.

3. Tilpasset validering

Å lage en tilpasset validator innebærer at vi ruller ut vår egen kommentar og bruker den i vår modell for å håndheve valideringsreglene.

Så la oss lage våre tilpasset validator - som sjekker telefonnumre. Telefonnummeret må være et nummer med mer enn åtte sifre, men ikke mer enn 11 sifre.

4. Den nye merknaden

La oss lage et nytt @grensesnitt for å definere kommentaren vår:

@Documented @Constraint (validatedBy = ContactNumberValidator.class) @Target ({ElementType.METHOD, ElementType.FIELD}) @Retention (RetentionPolicy.RUNTIME) public @interface ContactNumberConstraint {Strengmelding () standard "Ugyldig telefonnummer"; Klasse [] grupper () standard {}; Klasse [] nyttelast () standard {}; }

Med @Begrensning kommentar, vi definerte klassen som skal validere vårt felt, the beskjed() er feilmeldingen som vises i brukergrensesnittet, og tilleggskoden er den mest kjele koden for å være i samsvar med vårstandardene.

5. Opprette en validator

La oss nå opprette en validatorklasse som håndhever reglene for validering:

offentlig klasse ContactNumberValidator implementerer ConstraintValidator {@Override public void initialize (ContactNumberConstraint contactNumber) {} @Override public boolean isValid (String contactField, ConstraintValidatorContext cxt) {return contactField! = null && contactField.matches ("[0-9] (contactField.length ()> 8) && (contactField.length () <14); }}

Valideringsklassen implementerer ConstraintValidator grensesnitt og må implementere er gyldig metode; det er i denne metoden vi definerte valideringsreglene våre.

Naturligvis går vi med en enkel valideringsregel her for å vise hvordan validatoren fungerer.

ConstraintValidator ddefinerer logikken for å validere en gitt begrensning for et gitt objekt. Implementeringene må være i samsvar med følgende begrensning:

  • objektet må løse seg til en ikke-parametrisert type
  • generiske parametere for objektet må være ubegrensede jokertegnetyper

6. Bruke valideringskommentarer

I vårt tilfelle har vi opprettet en enkel klasse med ett felt for å bruke valideringsreglene. Her konfigurerer vi vårt merkede felt som skal valideres:

@ContactNumberConstraint privat strengtelefon;

Vi definerte et strengfelt og kommenterte det med vår egendefinerte kommentar @ContactNumberConstraint. I kontrolleren vår opprettet vi kartleggingen og håndterte feilen hvis noen:

@Controller public class ValidatedPhoneController {@GetMapping ("/ validatePhone") public String loadFormPage (Model m) {m.addAttribute ("validatedPhone", new ValidatedPhone ()); returner "phoneHome"; } @PostMapping ("/ addValidatePhone") public String submitForm (@Valid ValidatedPhone validatedPhone, BindingResult result, Model m) {if (result.hasErrors ()) {return "phoneHome"; } m.addAttribute ("melding", "Telefonen er vellykket lagret:" + validatedPhone.toString ()); returner "phoneHome"; }}

Vi definerte denne enkle kontrolleren som har en enkelt JSP siden, og bruk sendForm metode for å håndheve validering av telefonnummeret vårt.

7. Utsikten

Vårt syn er en grunnleggende JSP-side med et skjema som har ett enkelt felt. Når brukeren sender inn skjemaet, blir feltet validert av vår tilpassede validator og omdirigerer til samme side med meldingen om vellykket eller mislykket validering:

 Telefon: 

8. Tester

La oss nå teste kontrolleren vår og sjekke om den gir oss riktig respons og visning:

@Test offentlig ugyldig givenPhonePageUri_whenMockMvc_thenReturnsPhonePage () {this.mockMvc. utfør (get ("/ validatePhone")). ogExpect (visning (). navn ("phoneHome")); }

La oss også teste at feltet vårt er validert, basert på brukerinndata:

@Test offentlig ugyldig gittPhoneURIWithPostAndFormData_whenMockMVC_thenVerifyErrorResponse () {this.mockMvc.perform (MockMvcRequestBuilders.post ("/ addValidatePhone"). Godta (MediaType.TEXT_HTML). "." ("TelefonInput)." andExpect (model (). attributeHasFieldErrorCode ("validatedPhone", "phone", "ContactNumberConstraint")). andExpect (view (). name ("phoneHome")). ogExpect (status (). isOk ()). andDo (print ()); }

I testen gir vi brukeren inntastingen "123", og - som vi forventet - alt fungerer og vi ser feilen på klientsiden.

9. Validering av tilpasset klassenivå

En tilpasset valideringskommentar kan også defineres på klassenivå for å validere mer enn ett attributt for klassen.

En vanlig brukssak for dette scenariet er å verifisere om to felt i en klasse har samsvarende verdier.

9.1. Lage kommentaren

La oss legge til en ny kommentar som heter FieldsValueMatch som senere kan brukes på en klasse. Merknaden vil ha to parametere felt og fieldMatch som representerer navnene på feltene som skal sammenlignes:

@Constraint (validatedBy = FieldsValueMatchValidator.class) @Target ({ElementType.TYPE}) @Retention (RetentionPolicy.RUNTIME) public @interface FieldsValueMatch {Strengmelding () standard "Feltverdiene stemmer ikke overens!"; Strengfelt (); String fieldMatch (); @Target ({ElementType.TYPE}) @Retention (RetentionPolicy.RUNTIME) @interface List {FieldsValueMatch [] value (); }}

Vi kan se at vår tilpassede kommentar også inneholder en Liste undergrensesnitt for å definere flere FieldsValueMatch kommentarer på en klasse.

9.2. Opprette Validator

Deretter må vi legge til FieldsValueMatchValidator klasse som inneholder den faktiske valideringslogikken:

offentlig klasse FieldsValueMatchValidator implementerer ConstraintValidator {private strengfelt; private String fieldMatch; public void initialize (FieldsValueMatch constraintAnnotation) {this.field = constraintAnnotation.field (); this.fieldMatch = constraintAnnotation.fieldMatch (); } public boolean isValid (Object value, ConstraintValidatorContext context) {Object fieldValue = new BeanWrapperImpl (value) .getPropertyValue (field); Objekt fieldMatchValue = ny BeanWrapperImpl (verdi). GetPropertyValue (fieldMatch); hvis (fieldValue! = null) {return fieldValue.equals (fieldMatchValue); } annet {return fieldMatchValue == null; }}}

De er gyldig() metoden henter verdiene til de to feltene og sjekker om de er like.

9.3. Bruke merknaden

La oss lage en NewUserForm modellklasse beregnet på data som kreves for brukerregistrering, som har to e-post og passord attributter, sammen med to verifiser e-post og bekreft passord attributter for å angi de to verdiene på nytt.

Siden vi har to felt å sjekke mot de tilsvarende samsvarende feltene, la oss legge til to @FieldsValueMatch merknader om NewUserForm klasse, en for e-post verdier, og en for passord verdier:

@ FieldsValueMatch.List ({@FieldsValueMatch (field = "password", fieldMatch = "verifyPassword", message = "Passwords do not match!"), @FieldsValueMatch (field = "email", fieldMatch = "verifyEmail", message = " E-postadressene stemmer ikke overens! ")}) Offentlig klasse NewUserForm {privat streng-e-post; privat streng verifisereE-post; privat strengpassord; privat streng verifisere passord; // standard konstruktør, getters, setters}

For å validere modellen i Spring MVC, la oss lage en kontroller med en /bruker POST-kartlegging som mottar en NewUserForm objekt kommentert med @Gyldig og verifiserer om det er noen valideringsfeil:

@Controller public class NewUserController {@GetMapping ("/ user") public String loadFormPage (Model model) {model.addAttribute ("newUserForm", new NewUserForm ()); returner "userHome"; } @PostMapping ("/ user") public String submitForm (@Valid NewUserForm newUserForm, BindingResult result, Model model) {if (result.hasErrors ()) {return "userHome"; } model.addAttribute ("melding", "Gyldig skjema"); returner "userHome"; }}

9.4. Testing av kommentaren

For å bekrefte vår tilpassede merknad på klassenivå, la oss skrive en JUnit test som sender samsvarende informasjon til /bruker endepunkt, og verifiserer deretter at svaret ikke inneholder noen feil:

offentlig klasse ClassValidationMvcTest {private MockMvc mockMvc; @Før offentlige ugyldige oppsett () {this.mockMvc = MockMvcBuilders .standaloneSetup (ny NewUserController ()). Build (); } @Test offentlig ugyldig gittMatchingEmailPassword_whenPostNewUserForm_thenOk () kaster unntak {this.mockMvc.perform (MockMvcRequestBuilders .post ("/ user") .accept (MediaType.TEXT_HTML). .Param ("email", "[email protected]". ("verifisere e-post", "[e-postbeskyttet]") .param ("passord", "pass") .param ("verifisere passord", "pass")). og Expect (modell (). errorCount (0)). status (). isOk ()); }}

La oss også legge til en JUnit test som sender informasjon som ikke samsvarer med /bruker endepunkt og hevder at resultatet vil inneholde to feil:

@Test offentlig ugyldighet gittNotMatchingEmailPassword_whenPostNewUserForm_thenOk () kaster unntak {this.mockMvc.perform (MockMvcRequestBuilders .post ("/ user") .accept (MediaType.TEXT_HTML) .param ("email", "[e-postbeskyttet]".) verifyEmail "," [email protected] ") .param (" password "," pass ") .param (" verifyPassword "," passsss ")). andExpect (model (). errorCount (2)). andExpect (status ( ) .isOk ()); }

10. Sammendrag

I denne raske artikkelen har vi vist hvordan du lager egendefinerte validatorer for å verifisere et felt eller en klasse og koble dem til Spring MVC.

Som alltid kan du finne koden fra artikkelen på Github.


$config[zx-auto] not found$config[zx-overlay] not found