Spring Boot – walidacja na poziomie beana


Spring Boot – walidacja na poziomie beana

Walidacja to podstawowy mechanizm zabezpieczający system przed wprowadzeniem przez użytkownika niepoprawnych danych. W tym artykule dowiesz się w jaki sposób z użyciem Spring Boota dokonać walidacji określonych pól klasy modelu przesłanych w formularzu przez użytkownika. Do dzieła! Tworzymy nowy projekt Spring Boota – niezbędne zależności – plik pom.xml:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
 
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-thymeleaf</artifactId>
	</dependency>
 
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

Klasa modelu z polami oznaczonymi adnotacjami z pakietu javax.validation.constraints, zakładamy, że imię mieści się w przedziale od 3 do 7 znaków a wiek to minimum 18 lat:

import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
 
public class User {
 
    @Size(min =3, max = 7)
    private String name;
 
    @Min(18)
    private int age;
 
    public User() {
    }
 
    public User(@Size(min = 3, max = 7) String name, @NotEmpty(message = "field age is empty!") int age) {
        this.name = name;
        this.age = age;
    }
 
   // setters & getters
}

Klasa kontrolera – adnotacja @Valid musi być przed adnotacją @ModelAttribute. Obiekt typu BindingResult zawierać będzie informacje o błędach, jeśli takowe wystąpią zostaną one wyświetlone na konsoli:

@Controller
public class UserController {
 
    @GetMapping("/user")
    public String userView(Model model){
        model.addAttribute("user", new User("name", 0));
        return "userView";
    }
 
    @PostMapping("/user")
    public String userView(@Valid @ModelAttribute User user, BindingResult bindingResult){
 
        if(bindingResult.hasErrors()){
            List<ObjectError> errorsList = bindingResult.getAllErrors();
            for(ObjectError error:errorsList) {
                System.out.println(error);
            }
 
        }
        return "userView";
    }
}

Jako, że korzystamy z systemu szablonów thymeleaf to plik widoku userView powinien być zamieszczony w katalogu ./templates. Poniżej formularz userView.html z użyciem thymeleafa:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
<form th:action="@{/user}" th:object="${user}" method="post">
 
    <!-- print all errors from form -->
    <div class="alert alert-danger" th:if="${#fields.hasErrors('*')}">
        <p th:each="err : ${#fields.errors('*')}" th:text="${err}">        </p>
    </div>
 
    <p><input  type = "text"   th:field="*{name}"  placeholder = "name" /> </p>
    <p><input  type = "text"   th:field="*{age}"   placeholder = 0 />      </p>
    <input     type = "submit" value="Validate" />
 
</form>
</body>
</html>

zaprezentowany formularz z użyciem operatora selekcji – * wnioskuje jakie pola mają być związane z przekazanym z poziomu kontrolera do widoku atrybutem modelu:

model.addAttribute("user", new User("name", 0));

Po uruchomieniu aplikacji:

http://localhost:8098/user

wyświetli się formularz html:

Po podaniu niepoprawnych danych, otrzymamy komunikat:

size must be between 3 and 7
 
must be greater than or equal to 18

Jeśli informacja o błędach ma się pojawić przy konkretnym polu to należy przy nim dodać paragraf odpowiednio dla pola name:

<p th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></p>

dla pola age:

<p th:if="${#fields.hasErrors('age')}" th:errors="*{age}"> </p>


Leave a comment

Your email address will not be published.


*