Formuliervalidatie met AngularJS en Spring MVC

1. Overzicht

Validatie is nooit zo eenvoudig als we verwachten. En natuurlijk is het valideren van de waarden die door een gebruiker in een applicatie zijn ingevoerd erg belangrijk voor het behouden van de integriteit van onze gegevens.

In de context van een webtoepassing wordt de gegevensinvoer meestal gedaan met behulp van HTML-formulieren en is zowel validatie aan de clientzijde als aan de serverzijde vereist.

In deze tutorial zullen we kijken naar implementatie van client-side validatie van formulierinvoer met behulp van AngularJS en server-side validatie met behulp van het Spring MVC-framework.

Dit artikel richt zich op Spring MVC. In ons artikel Validatie in Spring Boot wordt beschreven hoe u validaties uitvoert in Spring Boot.

2. Maven afhankelijkheden

Laten we om te beginnen de volgende afhankelijkheden toevoegen:

 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 nieuwste versies van spring-webmvc, hibernate-validator en jackson-databind kunnen worden gedownload van Maven Central.

3. Validatie met behulp van Spring MVC

Een applicatie mag nooit alleen vertrouwen op validatie aan de clientzijde, aangezien dit gemakkelijk kan worden omzeild. Om te voorkomen dat onjuiste of kwaadaardige waarden worden opgeslagen of een onjuiste uitvoering van de applicatielogica veroorzaken, is het belangrijk om invoerwaarden ook aan de serverzijde te valideren.

Spring MVC biedt ondersteuning voor server-side validatie door gebruik te maken van JSR 349 ​​Bean-validatie specificatie annotaties. Voor dit voorbeeld gebruiken we de referentie-implementatie van de specificatie, namelijk slaapstand-validator.

3.1. Het datamodel

Laten we een Gebruiker klasse met eigenschappen die zijn geannoteerd met de juiste validatie-annotaties:

openbare klasse Gebruiker {@NotNull @Email privé String e-mail; @NotNull @Size (min = 4, max = 15) privé String-wachtwoord; @NotBlank private String naam; @Min (18) @Digits (geheel getal = 2, fractie = 0) privé int leeftijd; // standard constructor, getters, setters}

De hierboven gebruikte annotaties behoren tot de JSR 349 specificatie, met uitzondering van @E-mail en @RTLnieuws, die specifiek zijn voor de slaapstand-validator bibliotheek.

3.2. Veer MVC-controller

Laten we een controllerklasse maken die een /gebruiker eindpunt, dat zal worden gebruikt om een ​​nieuw Gebruiker bezwaar maken tegen een Lijst.

Om validatie van het Gebruiker object ontvangen via verzoekparameters, moet de declaratie worden voorafgegaan door de @Geldig annotatie, en de validatiefouten worden bewaard in een BindingResult voorbeeld.

Om te bepalen of het object ongeldige waarden bevat, kunnen we de hasErrors () methode van BindingResult.

Als hasErrors () geeft terug waar, kunnen we een JSON-array met de foutmeldingen die zijn gekoppeld aan de validaties die niet zijn geslaagd. Anders zullen we het object aan de lijst toevoegen:

@PostMapping (value = "/ user") @ResponseBody openbare ResponseEntity saveUser (@Valid User-gebruiker, BindingResult-resultaat, Modelmodel) {if (result.hasErrors ()) {Lijstfouten = result.getAllErrors (). Stream (). map (DefaultMessageSourceResolvable :: getDefaultMessage) .collect (Collectors.toList ()); retourneer nieuwe ResponseEntity (fouten, HttpStatus.OK); } else {if (users.stream (). anyMatch (it -> user.getEmail (). equals (it.getEmail ()))) {retourneer nieuwe ResponseEntity (Collections.singletonList ("E-mail bestaat al!"), HttpStatus .CONFLICT); } else {gebruikers.add (gebruiker); retourneer nieuwe ResponseEntity (HttpStatus.CREATED); }}}

Zoals je kunt zien, validatie aan de serverzijde voegt het voordeel toe dat er aanvullende controles kunnen worden uitgevoerd die aan de clientzijde niet mogelijk zijn.

In ons geval kunnen we controleren of een gebruiker met hetzelfde e-mailadres al bestaat - en de status 409 CONFLICT retourneren als dat het geval is.

We moeten ook onze lijst met gebruikers definiëren en deze initialiseren met een paar waarden:

private List users = Arrays.asList (nieuwe gebruiker ("[email protected]", "pass", "Ana", 20), nieuwe gebruiker ("[email protected]", "pass", "Bob", 30), nieuwe gebruiker ("[email protected]", "pass", "John", 40), nieuwe gebruiker ("[email protected]", "pass", "Mary", 30));

Laten we ook een toewijzing toevoegen om de lijst met gebruikers op te halen als een JSON-object:

@GetMapping (value = "/ users") @ResponseBody openbare lijst getUsers () {terugkerende gebruikers; }

Het laatste item dat we nodig hebben in onze Spring MVC-controller is een mapping om de hoofdpagina van onze applicatie te retourneren:

@GetMapping ("/ userPage") public String getUserProfilePage () {return "user"; }

We zullen de gebruiker.html pagina in meer detail in de AngularJS-sectie.

3.3. Spring MVC-configuratie

Laten we een basis MVC-configuratie toevoegen aan onze applicatie:

@Configuration @EnableWebMvc @ComponentScan (basePackages = "com.baeldung.springmvcforms") klasse ApplicationConfiguration implementeert WebMvcConfigurer {@Override public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) {configurer.enable (); } @Bean openbare InternalResourceViewResolver htmlViewResolver () {InternalResourceViewResolver bean = nieuwe InternalResourceViewResolver (); bean.setPrefix ("/ WEB-INF / html /"); bean.setSuffix (". html"); terugkeer boon; }}

3.4. Initialiseren van de applicatie

Laten we een klasse maken die implementeert WebApplicationInitializer interface om onze applicatie uit te voeren:

openbare klasse WebInitializer implementeert WebApplicationInitializer {public void onStartup (ServletContext-container) gooit ServletException {AnnotationConfigWebApplicationContext ctx = nieuwe AnnotationConfigWebApplicationContext (); ctx.register (ApplicationConfiguration.class); ctx.setServletContext (container); container.addListener (nieuwe ContextLoaderListener (ctx)); ServletRegistration.Dynamic servlet = container.addServlet ("dispatcher", nieuwe DispatcherServlet (ctx)); servlet.setLoadOnStartup (1); servlet.addMapping ("/"); }}

3.5. Spring Mvc-validatie testen met behulp van Curl

Voordat we de AngularJS-clientsectie implementeren, kunnen we onze API testen met cURL met het commando:

curl -i -X ​​POST -H "Accepteer: applicatie / json" "localhost: 8080 / spring-mvc-formulieren / gebruiker? email = aaa & wachtwoord = 12 & leeftijd = 12"

Het antwoord is een array met de standaard foutmeldingen:

["geen juist e-mailadres", "grootte moet tussen 4 en 15 zijn", "mag niet leeg zijn", "moet groter zijn dan of gelijk zijn aan 18"]

4. AngularJS-validatie

Validatie aan de clientzijde is nuttig bij het creëren van een betere gebruikerservaring, omdat het de gebruiker informatie geeft over hoe hij met succes geldige gegevens kan indienen en de interactie met de applicatie kan blijven voortzetten.

De AngularJS-bibliotheek biedt uitstekende ondersteuning voor het toevoegen van validatievereisten aan formuliervelden, het afhandelen van foutmeldingen en het opmaken van geldige en ongeldige formulieren.

Laten we eerst een AngularJS-module maken die het ngMessages module, die wordt gebruikt voor validatieberichten:

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

Laten we vervolgens een AngularJS-service en -controller maken die de API gebruiken die in de vorige sectie is gebouwd.

4.1. De AngularJS-service

Onze service heeft twee methoden die de MVC-controllermethoden aanroepen: een om een ​​gebruiker op te slaan en een om de lijst met gebruikers op te halen:

app.service ('UserService', ['$ http', function ($ http) {this.saveUser = function saveUser (user) {return $ http ({methode: 'POST', url: 'user', params: { email: user.email, wachtwoord: user.password, name: user.name, age: user.age}, headers: 'Accept: application / json'});} this.getUsers = function getUsers () {return $ http ({methode: 'GET', url: 'gebruikers', headers: 'Accept: application / json'}). then (function (response) {return response.data;});}}]);

4.2. De AngularJS-controller

De UserCtrl controller injecteert het Gebruikersservice, roept de servicemethoden op en behandelt de reactie- en foutmeldingen:

app.controller ('UserCtrl', ['$ scope', 'UserService', function ($ scope, UserService) {$ scope.submitted = false; $ scope.getUsers = function () {UserService.getUsers (). dan ( function (data) {$ scope.users = data;});} $ scope.saveUser = function () {$ scope.submitted = true; if ($ scope.userForm. $ valid) {UserService.saveUser ($ scope. user) .then (function success (response) {$ scope.message = 'Gebruiker toegevoegd!'; $ scope.errorMessage = ''; $ scope.getUsers (); $ scope.user = null; $ scope.submitted = false ;}, functiefout (antwoord) {if (response.status == 409) {$ scope.errorMessage = response.data.message;} else {$ scope.errorMessage = 'Fout bij toevoegen van gebruiker!';} $ scope.message = '';});}} $ scope.getUsers ();}]);

We kunnen in het bovenstaande voorbeeld zien dat de servicemethode alleen wordt aangeroepen als de $ geldig eigendom van userForm is waar. Toch is er in dit geval de extra controle op dubbele e-mails, die alleen op de server kan worden gedaan en afzonderlijk wordt afgehandeld in de fout() functie.

Merk ook op dat er een ingediend variabele gedefinieerd die ons zal vertellen of het formulier is verzonden of niet.

In eerste instantie zal deze variabele zijn false, en op inroeping van de saveUser () methode, wordt het waar. Als we niet willen dat validatieberichten worden weergegeven voordat de gebruiker het formulier verzendt, kunnen we de ingediend variabele om dit te voorkomen.

4.3. Formulier met AngularJS-validatie

Om gebruik te kunnen maken van de AngularJS-bibliotheek en onze AngularJS-module, moeten we de scripts toevoegen aan onze gebruiker.html bladzijde:

Dan kunnen we onze module en controller gebruiken door de ng-app en ng-controller eigendommen:

Laten we ons HTML-formulier maken:

 ... 

Merk op dat we de novalidate attribuut op het formulier om standaard HTML5-validatie te voorkomen en deze te vervangen door onze eigen.

De ng-klasse attribuut voegt het vormfout CSS-klasse dynamisch naar het formulier als het ingediend variabele heeft een waarde van waar.

De ng-submit attribuut definieert de AngularJS-controllerfunctie die wordt aangeroepen wanneer het formulier wordt verzonden. Gebruik makend van ng-submit in plaats van ng-klik heeft als voordeel dat het ook reageert op het indienen van het formulier met de ENTER-toets.

Laten we nu de vier invoervelden voor de gebruikersattributen toevoegen:

E-mail: Wachtwoord: Naam: Leeftijd: 

Elk invoerveld heeft een binding met een eigenschap van de gebruiker variabele via de ng-model attribuut.

Voor het instellen van validatieregelsgebruiken we de HTML5 verplicht attribuut en verschillende AngularJS-specifieke attributen: ng-minglength, ng-maxlength, ng-min, en ng-trim.

Voor de e-mail veld gebruiken we ook de type attribuut met de waarde e-mail voor e-mailvalidatie aan de clientzijde.

Om foutmeldingen toe te voegen die overeenkomen met elk veld, AngularJS biedt de ng-berichten richtlijn, die doorloopt via een input $ fouten object en geeft berichten weer op basis van elke validatieregel.

Laten we de richtlijn voor de e-mail veld direct na de invoerdefinitie:

Ongeldig e-mail!

E-mail is verplicht!

Soortgelijke foutmeldingen kunnen worden toegevoegd voor de andere invoervelden.

We kunnen bepalen wanneer de richtlijn wordt weergegeven voor de e-mail veld met behulp van de ng-show eigenschap met een booleaanse uitdrukking. In ons voorbeeld geven we de instructie weer wanneer het veld een ongeldige waarde heeft, wat betekent dat de $ ongeldig eigendom is waar, en de ingediend variabele is ook waar.

Voor een veld wordt slechts één foutmelding tegelijk weergegeven.

We kunnen ook een vinkje toevoegen (weergegeven door HEX-codeteken ✓) achter het invoerveld voor het geval het veld geldig is, afhankelijk van de $ geldig eigendom:

AngularJS-validatie biedt ook ondersteuning voor styling met behulp van CSS-klassen zoals ng-geldig en ng-ongeldig of meer specifieke zoals ng-invalid-required en ng-invalid-minlength.

Laten we de CSS-eigenschap toevoegen randkleur: rood voor ongeldige invoer in het formulier vormfout klasse:

.form-error input.ng-invalid {border-color: rood; }

We kunnen de foutmeldingen ook in het rood weergeven met behulp van een CSS-klasse:

.foutmeldingen {kleur: rood; }

Laten we, nadat we alles hebben samengevoegd, een voorbeeld bekijken van hoe onze client-side formuliervalidatie eruit zal zien wanneer deze wordt ingevuld met een combinatie van geldige en ongeldige waarden:

5. Conclusie

In deze tutorial hebben we laten zien hoe we client-side en server-side validatie kunnen combineren met AngularJS en Spring MVC.

Zoals altijd is de volledige broncode voor de voorbeelden te vinden op GitHub.

Open het / userPage URL na het uitvoeren ervan.