Formvalidering med AngularJS og Spring MVC

1. Oversigt

Validering er aldrig lige så ligetil som vi forventer. Og selvfølgelig er validering af de værdier, der er indtastet af en bruger i en applikation, meget vigtig for at bevare integriteten af ​​vores data.

I forbindelse med en webapplikation foretages datainput normalt ved hjælp af HTML-formularer og kræver både validering af klientsiden og serversiden.

I denne vejledning skal vi se på implementering af klientsides validering af formularinput ved hjælp af AngularJS og serversides validering ved hjælp af Spring MVC framework.

Denne artikel fokuserer på Spring MVC. Vores artikel Validering i Spring Boot beskriver, hvordan du foretager valideringer i Spring Boot.

2. Maven-afhængigheder

For at starte, lad os tilføje følgende afhængigheder:

 org.springframework spring-webmvc 4.3.7.RELEASE org.hibernate hibernate-validator 5.4.0.Final com.fasterxml.jackson.core jackson-databind 2.8.7 

De nyeste versioner af spring-webmvc, hibernate-validator og jackson-databind kan downloades fra Maven Central.

3. Validering ved hjælp af fjeder-MVC

En applikation bør aldrig stole udelukkende på validering på klientsiden, da dette let kan omgåes. For at forhindre, at forkerte eller ondsindede værdier gemmes eller forårsager forkert udførelse af applikationslogikken, er det vigtigt også at validere inputværdier på serversiden.

Spring MVC tilbyder support til serversidevalidering ved hjælp af JSR 349 ​​Bønnevalidering specifikationskommentarer. I dette eksempel bruger vi referenceimplementeringen af ​​specifikationen, som er dvale-validator.

3.1. Datamodellen

Lad os oprette en Bruger klasse, der har egenskaber, der er kommenteret med passende valideringsannoteringer:

offentlig klasse bruger {@NotNull @Email privat streng-mail; @NotNull @Size (min = 4, max = 15) privat strengadgangskode; @NotBlank privat strengnavn; @Min (18) @Digits (heltal = 2, brøkdel = 0) privat int alder; // standard konstruktør, getters, setters}

Ovennævnte annoteringer hører til JSR 349 specifikation, med undtagelse af @E-mail og @NotBlank, som er specifikke for dvale-validator bibliotek.

3.2. Fjeder MVC-controller

Lad os oprette en controller-klasse, der definerer en /bruger slutpunkt, som vil blive brugt til at gemme et nyt Bruger modsætter sig en Liste.

For at muliggøre validering af Bruger objekt modtaget via anmodningsparametre, skal erklæringen være forud for @Gyldig kommentar, og valideringsfejlene opbevares i en Bindende resultat eksempel.

For at afgøre, om objektet indeholder ugyldige værdier, kan vi bruge hasErrors () metode til Bindende resultat.

Hvis hasErrors () vender tilbage rigtigt, vi kan returnere en JSON-array indeholder de fejlmeddelelser, der er knyttet til de valideringer, der ikke bestod. Ellers tilføjer vi objektet til listen:

@PostMapping (værdi = "/ bruger") @ResponseBody public ResponseEntity saveUser (@Valid User user, BindingResult result, Model model) {if (result.hasErrors ()) {List errors = result.getAllErrors (). Stream (). kort (DefaultMessageSourceResolvable :: getDefaultMessage) .collect (Collectors.toList ()); returner ny ResponseEntity (fejl, HttpStatus.OK); } ellers {if (users.stream (). anyMatch (it -> user.getEmail (). er lig med (it.getEmail ()))) {returner ResponseEntity (Collections.singletonList ("E-mail eksisterer allerede!"), HttpStatus .KONFLIKT); } andet {users.add (bruger); returner ny ResponseEntity (HttpStatus.CREATED); }}}

Som du kan se, validering på serversiden tilføjer fordelen ved at have evnen til at udføre yderligere kontrol, der ikke er mulig på klientsiden.

I vores tilfælde kan vi kontrollere, om en bruger med den samme e-mail allerede findes - og returnere en status på 409 KONFLIKT, hvis det er tilfældet.

Vi skal også definere vores liste over brugere og initialisere den med et par værdier:

private List-brugere = Arrays.asList (ny bruger ("[email protected]", "pass", "Ana", 20), ny bruger ("[email protected]", "pass", "Bob", 30), ny bruger ("[email protected]", "pass", "John", 40), new User ("[email protected]", "pass", "Mary", 30));

Lad os også tilføje en kortlægning for at hente listen over brugere som et JSON-objekt:

@GetMapping (værdi = "/ brugere") @ResponseBody offentlig Liste getUsers () {returnere brugere; }

Det sidste element, vi har brug for i vores Spring MVC-controller, er en kortlægning for at returnere hovedsiden i vores ansøgning:

@GetMapping ("/ userPage") offentlig streng getUserProfilePage () {returner "bruger"; }

Vi tager et kig på bruger.html side mere detaljeret i AngularJS sektionen.

3.3. Spring MVC Configuration

Lad os tilføje en grundlæggende MVC-konfiguration til vores applikation:

@Configuration @EnableWebMvc @ComponentScan (basePackages = "com.baeldung.springmvcforms") klasse ApplicationConfiguration implementerer WebMvcConfigurer {@ Override public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) (konfigurerbar) {konfigurer; } @Bean offentlig InternalResourceViewResolver htmlViewResolver () {InternalResourceViewResolver bean = ny InternalResourceViewResolver (); bean.setPrefix ("/ WEB-INF / html /"); bean.setSuffix (". html"); retur bønne; }}

3.4. Initialisering af applikationen

Lad os oprette en klasse, der implementeres WebApplicationInitializer interface til at køre vores applikation:

offentlig klasse WebInitializer implementerer WebApplicationInitializer {public void onStartup (ServletContext container) kaster ServletException {AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext (); ctx.register (ApplicationConfiguration.class); ctx.setServletContext (container); container.addListener (ny ContextLoaderListener (ctx)); ServletRegistration.Dynamic servlet = container.addServlet ("dispatcher", ny DispatcherServlet (ctx)); servlet.setLoadOnStartup (1); servlet.addMapping ("/"); }}

3.5. Test af Spring Mvc-validering ved hjælp af Curl

Før vi implementerer AngularJS-klientsektionen, kan vi teste vores API ved hjælp af cURL med kommandoen:

curl -i -X ​​POST -H "Accepter: applikation / json" "localhost: 8080 / spring-mvc-forms / user? email = aaa & password = 12 & age = 12"

Svaret er et array, der indeholder standardfejlmeddelelserne:

["ikke en velformet e-mail-adresse", "størrelse skal være mellem 4 og 15", "må ikke være tom", "skal være større end eller lig med 18"]

4. AngularJS-validering

Validering på klientsiden er nyttig til at skabe en bedre brugeroplevelse, da det giver brugeren information om, hvordan man med succes kan indsende gyldige data og gør det muligt for dem at kunne fortsætte med at interagere med applikationen.

AngularJS-biblioteket har stor understøttelse af tilføjelse af valideringskrav til formularfelter, håndtering af fejlmeddelelser og styling af gyldige og ugyldige formularer.

Lad os først oprette et AngularJS-modul, der injicerer ngMeddelelser modul, der bruges til valideringsmeddelelser:

var app = angular.module ('app', ['ngMessages']);

Lad os derefter oprette en AngularJS-tjeneste og controller, der bruger det API, der er bygget i det foregående afsnit.

4.1. AngularJS-tjenesten

Vores service vil have to metoder, der kalder MVC-controllermetoderne - en for at gemme en bruger og en for at hente listen over brugere:

app.service ('UserService', ['$ http', funktion ($ http) {this.saveUser = funktion saveUser (bruger) {return $ http ({metode: 'POST', url: 'bruger', params: { email: user.email, password: user.password, name: user.name, age: user.age}, headers: 'Accept: application / json'});} this.getUsers = function getUsers () {return $ http ({metode: 'GET', url: 'brugere', overskrifter: 'Accepter: applikation / json'}). derefter (funktion (respons) {return response.data;});}}]);

4.2. AngularJS-controlleren

Det BrugerCtrl controller indsprøjter UserService, kalder servicemetoderne og håndterer svar- og fejlmeddelelser:

app.controller ('UserCtrl', ['$ scope', 'UserService', funktion ($ scope, UserService) {$ scope.subitted = false; $ scope.getUsers = funktion () {UserService.getUsers (). derefter ( funktion (data) {$ scope.users = data;});} $ scope.saveUser = funktion () {$ scope.subitted = true; hvis ($ scope.userForm. $ gyldig) {UserService.saveUser ($ scope. bruger). derefter (funktion succes (respons) {$ scope.message = 'Bruger tilføjet!'; $ scope.errorMessage = ''; $ scope.getUsers (); $ scope.user = null; $ scope.subitted = false ;}, funktionsfejl (respons) {if (respons.status == 409) {$ scope.errorMessage = respons.data.message;} ellers {$ scope.errorMessage = 'Fejl ved tilføjelse af bruger!';} $ scope.message = '';});}} $ scope.getUsers ();}]);

Vi kan se i eksemplet ovenfor, at servicemetoden kun kaldes, hvis $ gyldig ejendom af userForm er sandt. I dette tilfælde er der stadig den ekstra kontrol for duplikerede e-mails, som kun kan udføres på serveren og håndteres separat i fejl() fungere.

Bemærk også, at der er en indsendt variabel defineret, som fortæller os, om formularen er indsendt eller ej.

Oprindeligt vil denne variabel være falskog ved påkaldelse af gem bruger () metode, bliver det rigtigt. Hvis vi ikke ønsker, at valideringsmeddelelser skal vises, før brugeren sender formularen, kan vi bruge indsendt variabel for at forhindre dette.

4.3. Formular ved hjælp af AngularJS-validering

For at gøre brug af AngularJS-biblioteket og vores AngularJS-modul skal vi tilføje scripts til vores bruger.html side:

Derefter kan vi bruge vores modul og controller ved at indstille ng-app og ng-controller ejendomme:

Lad os oprette vores HTML-formular:

 ... 

Bemærk, at vi skal indstille forny attribut på formularen for at forhindre standard HTML5-validering og erstatte den med vores egen.

Det ng-klasse attribut tilføjer form-fejl CSS klasse dynamisk til formularen, hvis indsendt variabel har en værdi på rigtigt.

Det ng-indsend attribut definerer AngularJS controller-funktionen, der kaldes, når formularen er indsendt. Ved brug af ng-indsend i stedet for ng-klik har den fordel, at den også reagerer på indsendelse af formularen ved hjælp af ENTER-tasten.

Lad os nu tilføje de fire inputfelter til brugerattributterne:

E-mail: Adgangskode: Navn: Alder: 

Hvert inputfelt har en binding til en egenskab af bruger variabel gennem ng-model attribut.

Til indstilling af valideringsregler, bruger vi HTML5 krævet attribut og flere AngularJS-specifikke attributter: ng-blandelængde, ng-maks. længde, ng-min, og ng-trim.

Til e-mail felt, bruger vi også type attribut med en værdi på e-mail til validering af e-mail på klientsiden.

For at tilføje fejlmeddelelser, der svarer til hvert felt, AngularJS tilbyder ng-beskeder direktiv, som løber gennem et input $ fejl objekt og viser meddelelser baseret på hver valideringsregel.

Lad os tilføje direktivet til e-mail felt lige efter inputdefinitionen:

Ugyldig email!

E-mail er påkrævet!

Lignende fejlmeddelelser kan tilføjes for de andre indtastningsfelter.

Vi kan kontrollere, hvornår direktivet vises til e-mail felt ved hjælp af ng-show ejendom med et boolsk udtryk. I vores eksempel viser vi direktivet, når feltet har en ugyldig værdi, hvilket betyder $ ugyldig ejendom er rigtigt, og indsendt variabel er også rigtigt.

Kun en fejlmeddelelse vises ad gangen for et felt.

Vi kan også tilføje et afkrydsningstegn (repræsenteret af HEX-kodetegn ✓) efter indtastningsfeltet, hvis feltet er gyldigt, afhængigt af $ gyldig ejendom:

AngularJS-validering tilbyder også support til styling ved hjælp af CSS-klasser som f.eks ng-gyldig og ng-ugyldig eller mere specifikke som ng-ugyldig-krævet og ng-ugyldig-minlængde.

Lad os tilføje CSS-ejendommen kantfarve: rød for ugyldige input i formularerne form-fejl klasse:

.form-error input.ng-ugyldig {border-color: red; }

Vi kan også vise fejlmeddelelserne i rødt ved hjælp af en CSS-klasse:

.fejlmeddelelser {farve: rød; }

Efter at have sat alt sammen, lad os se et eksempel på, hvordan vores formularvalidering på klientsiden ser ud, når den udfyldes med en blanding af gyldige og ugyldige værdier:

5. Konklusion

I denne vejledning har vi vist, hvordan vi kan kombinere klientside- og serversides validering ved hjælp af AngularJS og Spring MVC.

Som altid kan den fulde kildekode til eksemplerne findes på GitHub.

For at se applikationen skal du åbne / userPage URL efter at have kørt den.