Dlaczego walidacja danych jest ważna?
Każda aplikacja webowa musi weryfikować dane otrzymywane od użytkowników. Bez walidacji twoja aplikacja może otrzymać niepoprawne dane, które spowodują błędy w bazie danych, problemy z bezpieczeństwem lub po prostu nieprzewidywalne zachowanie. Spring Validation rozwiązuje ten problem w elegancki sposób, pozwalając na deklaratywne określenie reguł walidacji.
Co się nauczysz:
- Jak skonfigurować walidację w Spring Boot
- Jakie są najważniejsze adnotacje walidacyjne
- Jak walidować dane w kontrolerach
- Jak obsługiwać błędy walidacji
- Jak tworzyć własne walidatory
Czym jest Spring Validation?
Spring Validation to mechanizm oparty na standardzie JSR-303 (Bean Validation), który pozwala na automatyczne sprawdzanie poprawności obiektów Java. Zamiast pisać ręcznie kod sprawdzający każde pole, używasz adnotacji które określają reguły walidacji.
Konfiguracja Spring Validation
W Spring Boot 2.x walidacja jest włączona domyślnie. Wystarczy dodać zależność do pom.xml:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
Podstawowe adnotacje walidacyjne
Spring Validation oferuje bogaty zestaw gotowych adnotacji do walidacji. Oto najważniejsze z nich:
Adnotacja | Zastosowanie | Przykład |
---|---|---|
@NotNull | Pole nie może być null | @NotNull String name |
@NotEmpty | String/Collection nie może być pusty | @NotEmpty String email |
@NotBlank | String nie może być pusty lub składać się z białych znaków | @NotBlank String username |
@Size | Kontroluje rozmiar String/Collection | @Size(min=2, max=50) String name |
Sprawdza format adresu email | @Email String email | |
@Min/@Max | Minimalna/maksymalna wartość liczbowa | @Min(18) int age |
Tworzenie klasy z walidacją
Zobaczmy jak wygląda typowa klasa DTO z adnotacjami walidacyjnymi:
public class UserRegistrationDto { @NotBlank(message = "Imię nie może być puste") @Size(min = 2, max = 50, message = "Imię musi mieć od 2 do 50 znaków") private String firstName; @NotBlank(message = "Nazwisko nie może być puste") @Size(min = 2, max = 50, message = "Nazwisko musi mieć od 2 do 50 znaków") private String lastName; @NotBlank(message = "Email nie może być pusty") @Email(message = "Niepoprawny format emaila") private String email; @NotNull(message = "Wiek jest wymagany") @Min(value = 18, message = "Musisz mieć co najmniej 18 lat") @Max(value = 120, message = "Wiek nie może przekraczać 120 lat") private Integer age; // konstruktory, gettery i settery public UserRegistrationDto() {} public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
Walidacja w kontrolerach
Aby włączyć walidację w kontrolerze, używamy adnotacji @Valid lub @Validated:
@RestController @RequestMapping("/api/users") public class UserController { @PostMapping("/register") public ResponseEntity<String> registerUser(@Valid @RequestBody UserRegistrationDto user) { // Jeśli walidacja przejdzie pomyślnie, kod się wykona // W przeciwnym razie zostanie rzucony MethodArgumentNotValidException // Logika rejestracji użytkownika System.out.println("Rejestracja użytkownika: " + user.getFirstName() + " " + user.getLastName()); return ResponseEntity.ok("Użytkownik zarejestrowany pomyślnie"); } }
Obsługa błędów walidacji
Gdy walidacja się nie powiedzie, Spring rzuca wyjątek MethodArgumentNotValidException. Możemy go obsłużyć globalnie:
@ControllerAdvice public class ValidationExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<Map<String, String>> handleValidationExceptions( MethodArgumentNotValidException ex) { Map<String, String> errors = new HashMap<>(); // Przechodzimy przez wszystkie błędy walidacji ex.getBindingResult().getAllErrors().forEach((error) -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); return ResponseEntity.badRequest().body(errors); } }
Przykład odpowiedzi z błędami
Gdy wyślesz niepoprawne dane, otrzymasz odpowiedź JSON z szczegółami błędów:
{ "firstName": "Imię musi mieć od 2 do 50 znaków", "email": "Niepoprawny format emaila", "age": "Musisz mieć co najmniej 18 lat" }
Walidacja zagnieżdżonych obiektów
Możesz walidować również zagnieżdżone obiekty używając @Valid:
public class UserWithAddressDto { @NotBlank private String name; @Valid // Ważne! Bez tego adres nie będzie walidowany @NotNull private AddressDto address; // gettery i settery } public class AddressDto { @NotBlank(message = "Ulica nie może być pusta") private String street; @NotBlank(message = "Miasto nie może być puste") private String city; @Pattern(regexp = "\\d{2}-\\d{3}", message = "Kod pocztowy musi być w formacie XX-XXX") private String zipCode; // gettery i settery }
@NotNull sprawdza czy wartość nie jest null. @NotEmpty sprawdza czy String/Collection nie jest pusty (ale może być null). @NotBlank sprawdza czy String nie jest pusty i nie składa się tylko z białych znaków.
Tak, JSR-303 Bean Validation to standard Java. Możesz używać implementacji jak Hibernate Validator również w zwykłych aplikacjach Java.
Użyj @Validated na klasie kontrolera i dodaj adnotacje walidacyjne do parametrów metod, np. @Min(1) @PathVariable Long id.
Walidacja działa automatycznie tylko gdy użyjesz @Valid lub @Validated. Bez tych adnotacji Spring nie będzie walidować danych.
Użyj MockMvc w testach Spring Boot: mockMvc.perform(post().content(invalidJson)).andExpect(status().isBadRequest())
Tak, możesz tworzyć grupy walidacji używając interfejsów jako markery i parametru groups w adnotacjach walidacyjnych.
Walidacja w Spring jest bardzo szybka. Adnotacje są przetwarzane przez reflection, ale wyniki są cache’owane. W praktyce overhead jest minimalny.
Przydatne zasoby:
- Spring Framework Validation Documentation
- Hibernate Validator – implementacja JSR-303
- Oracle Bean Validation Tutorial
🚀 Zadanie dla Ciebie
Stwórz formularz rejestracji z walidacją, który sprawdza: imię i nazwisko (min 2 znaki), email (poprawny format), hasło (min 8 znaków) i potwierdzenie hasła (musi być identyczne). Dodaj obsługę błędów i przetestuj z niepoprawymi danymi.
Czy używałeś już Spring Validation w swoich projektach? Jakie napotkałeś problemy z walidacją danych? Podziel się swoimi doświadczeniami w komentarzach!