Validatie in Spring Boot

1. Overzicht

Als het gaat om het valideren van gebruikersinvoer, biedt Spring Boot krachtige ondersteuning voor deze veel voorkomende, maar cruciale taak, direct uit de doos.

Hoewel Spring Boot naadloze integratie met aangepaste validators ondersteunt, de de facto standaard voor het uitvoeren van validatie is Hibernate Validator, de referentie-implementatie van het Bean Validation-raamwerk.

In deze tutorial we zullen bekijken hoe domeinobjecten in Spring Boot kunnen worden gevalideerd.

2. De afhankelijkheden van Maven

In dit geval leren we hoe u domeinobjecten valideert in Spring Boot door een basis REST-controller te bouwen.

De controller neemt eerst een domeinobject, valideert het vervolgens met Hibernate Validator en houdt het uiteindelijk vast in een H2-database in het geheugen.

De afhankelijkheden van het project zijn redelijk standaard:

 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa com.h2database h2 1.4.197 runtime 

Zoals hierboven getoond, hebben we inbegrepen spring-boot-starter-web in onze pom.xml bestand omdat we het nodig hebben voor het maken van de REST-controller. Laten we er bovendien voor zorgen dat we de nieuwste versies van spring-boot-starter-jpa en de H2-database op Maven Central.

Vanaf Boot 2.3 moeten we ook expliciet het spring-boot-starter-validation afhankelijkheid:

 org.springframework.boot spring-boot-starter-validation 

3. Een eenvoudige domeinklasse

Nu de afhankelijkheden van ons project al aanwezig zijn, moeten we vervolgens een voorbeeld van een JPA-entiteitsklasse definiëren, waarvan de rol uitsluitend het modelleren van gebruikers is.

Laten we deze les eens bekijken:

@Entity openbare klasse Gebruiker {@Id @GeneratedValue (strategie = GenerationType.AUTO) privé lang ID; @NotBlank (message = "Naam is verplicht") private String naam; @NotBlank (message = "E-mail is verplicht") private String e-mail; // standard constructors / setters / getters / toString}

De implementatie van onze Gebruiker entiteitsklasse is inderdaad behoorlijk bloedarm, maar het laat in een notendop zien hoe de beperkingen van Bean Validation kunnen worden gebruikt om de naam en e-mail velden.

Voor de eenvoud hebben we de doelvelden beperkt door alleen de @RTLnieuws beperking. We hebben ook de foutmeldingen gespecificeerd met de bericht attribuut.

Daarom, wanneer Spring Boot de klasse-instantie valideert, worden de beperkte velden mag niet nul zijn en hun bijgesneden lengte moet groter zijn dan nul.

Bovendien biedt Bean Validation naast vele andere handige beperkingen @RTLnieuws Dit stelt ons in staat om verschillende validatieregels toe te passen en te combineren op de beperkte klassen. Lees voor meer informatie de officiële bean-validatiedocumenten.

Omdat we Spring Data JPA gebruiken om gebruikers op te slaan in de H2-database in het geheugen, moeten we ook een eenvoudige repository-interface definiëren om basis CRUD-functionaliteit op Gebruiker voorwerpen:

@Repository openbare interface UserRepository breidt CrudRepository uit {}

4. Implementeren van een REST Controller

Natuurlijk moeten we een laag implementeren waarmee we de waarden kunnen krijgen die aan ons zijn toegewezen Gebruiker de beperkte velden van het object.

Daarom kunnen we ze valideren en een aantal andere taken uitvoeren, afhankelijk van de validatieresultaten.

Spring Boot maakt dit ogenschijnlijk complexe proces is heel eenvoudig door de implementatie van een REST-controller.

Laten we eens kijken naar de implementatie van de REST-controller:

@RestController openbare klasse UserController {@PostMapping ("/ users") ResponseEntity addUser (@Valid @RequestBody User user) {// de gebruiker blijft teruggeven ResponseEntity.ok ("User is valid"); } // standaard constructors / andere methoden} 

In een Spring REST-context is de implementatie van de Voeg gebruiker toe() methode is redelijk standaard.

Het meest relevante onderdeel is natuurlijk het gebruik van de @Geldig annotatie.

Wanneer Spring Boot een argument vindt dat is geannoteerd met @Geldig, start het automatisch de standaard JSR 380-implementatie - Hibernate Validator - en valideert het argument.

Wanneer het doelargument de validatie niet doorstaat, gooit Spring Boot een MethodArgumentNotValidException uitzondering.

5. Het @BuienRadarNL Annotatie

Hoewel het erg handig is om Spring Boot het Gebruiker object doorgegeven aan de Voeg gebruiker toe() methode automatisch, het ontbrekende facet van dit proces is hoe we de validatieresultaten verwerken.

De @BuienRadarNL annotatie stelt ons in staat om gespecificeerde soorten uitzonderingen af ​​te handelen via één enkele methode.

Daarom kunnen we het gebruiken voor het verwerken van de validatiefouten:

@ResponseStatus (HttpStatus.BAD_REQUEST) @ExceptionHandler (MethodArgumentNotValidException.class) public Map handleValidationExceptions (MethodArgumentNotValidException ex) {Map errors = new HashMap (); ex.getBindingResult (). getAllErrors (). forEach ((error) -> {String fieldName = ((FieldError) error) .getField (); String errorMessage = error.getDefaultMessage (); errors.put (fieldName, errorMessage); }); fouten teruggeven; }

We hebben de MethodArgumentNotValidException uitzondering als de te behandelen uitzondering. Daarom zal Spring Boot deze methode aanroepen wanneer de opgegeven Gebruiker object is ongeldig.

De methode slaat de naam en het postvalidatiefoutbericht van elk ongeldig veld op in een Kaart. Vervolgens wordt het Kaart terug naar de klant als een JSON-weergave voor verdere verwerking.

Simpel gezegd, de REST-controller stelt ons in staat om eenvoudig verzoeken naar verschillende eindpunten te verwerken en te valideren Gebruiker objecten en verzend de antwoorden in JSON-indeling.

Het ontwerp is flexibel genoeg om de reacties van de controller te verwerken via verschillende weblagen, variërend van sjabloonengines zoals Thymeleaf tot een volledig uitgerust JavaScript-framework zoals Angular.

6. Testen van de REST-controller

We kunnen de functionaliteit van onze REST-controller eenvoudig testen met een integratietest.

Laten we beginnen met het bespotten / automatisch bedraden van het UserRepository interface-implementatie, samen met de UserController instantie, en een MockMvc voorwerp:

@RunWith (SpringRunner.class) @WebMvcTest @AutoConfigureMockMvc openbare klasse UserControllerIntegrationTest {@MockBean privé UserRepository userRepository; @Autowired UserController userController; @Autowired privé MockMvc mockMvc; // ...} 

Omdat we alleen de weblaag testen, gebruiken we de @WebMvcTest annotatie. Het stelt ons in staat om eenvoudig verzoeken en antwoorden te testen met behulp van de set statische methoden die door de MockMvcRequestBuilders en MockMvcResultMatchers klassen.

Laten we nu het Voeg gebruiker toe() methode met een geldige en een ongeldige Gebruiker object doorgegeven in de hoofdtekst van het verzoek:

@Test public void whenPostRequestToUsersAndValidUser_thenCorrectResponse () genereert uitzondering {MediaType textPlainUtf8 = nieuw MediaType (MediaType.TEXT_PLAIN, Charset.forName ("UTF-8")); String user = "{\" naam \ ": \" bob \ ", \" email \ ": \" [e-mail beveiligd] \ "}"; mockMvc.perform (MockMvcRequestBuilders.post ("/ gebruikers") .content (gebruiker) .contentType (MediaType.APPLICATION_JSON_UTF8)) .andExpect (MockMvcResultMatchers.status (). isOk ()) .andExpect (MockMvcResultMatchers). textPlainUtf8)); } @Test public void whenPostRequestToUsersAndInValidUser_thenCorrectResponse () genereert uitzondering {String user = "{\" name \ ": \" \ ", \" email \ ": \" [e-mail beveiligd] \ "}"; mockMvc.perform (MockMvcRequestBuilders.post ("/ gebruikers") .content (gebruiker) .contentType (MediaType.APPLICATION_JSON_UTF8)) .andExpect (MockMvcResultMatchers.status (). isBadRequest ()) .andExpect (MockMvc "$. ", Is.is (" Naam is verplicht "))) .andExpect (MockMvcResultMatchers.content () .contentType (MediaType.APPLICATION_JSON_UTF8)); }} 

Daarnaast kunnen we de REST controller API testen met behulp van een gratis API-applicatie voor het testen van de levenscyclus, zoals Postman.

7. De voorbeeldtoepassing uitvoeren

Ten slotte kunnen we ons voorbeeldproject uitvoeren met een standaard hoofd() methode:

@SpringBootApplication openbare klasse Toepassing {openbare statische leegte hoofd (String [] args) {SpringApplication.run (Application.class, args); } @Bean openbare CommandLineRunner run (UserRepository userRepository) genereert uitzondering {return (String [] args) -> {User user1 = nieuwe gebruiker ("Bob", "[email protected]"); Gebruiker user2 = nieuwe gebruiker ("Jenny", "[email protected]"); userRepository.save (gebruiker1); userRepository.save (gebruiker2); userRepository.findAll (). forEach (System.out :: println); }; }} 

Zoals verwacht zouden we er een paar moeten zien Gebruiker objecten afgedrukt in de console.

Een POST-verzoek aan het // localhost: 8080 / gebruikers-eindpunt met een geldig Gebruiker object retourneert de Draad "Gebruiker is geldig".

Evenzo kan een POST-verzoek met een Gebruiker object zonder naam en e-mail waarden retourneren het volgende antwoord:

{"name": "Naam is verplicht", "email": "E-mail is verplicht"}

8. Conclusie

In dit artikel, we hebben de basisprincipes van validatie in Spring Boot geleerd.

Zoals gewoonlijk zijn alle voorbeelden die in dit artikel worden getoond, beschikbaar op GitHub.