Будем использовать механизм встроенных ограничений. Алгоритм использования встроенных ограничений следующий - с помощью аннотаций необходимо указать над полем класса-сущности требуемые параметры валидации и другие параметры. В нашем случае, сущностью выступает класс Student. Добавим необходимые ограничения для полей сущности.
Student.java
public class Student {
// Имя должно быть длиной от 2 до 50 символов
@Size(min = 2, max= 50, message = "First name should be from 2 to 50 characters")
private String firstName;
// Фамилия должна быть длиной от 2 до 50 символов
@Size(min = 2, max= 50, message = "Last name should be from 2 to 50 characters")
private String lastName;
// Возраст должен быть целым числом от 13 до 65
@Range(min = 13, max = 65, message = "Student age should be from 13 to 65 years")
private int age;
// Для валидации электронной почты используем регулярное выражение
@Pattern(regexp = "^[\\\\w!#$%&’*+/=?`{|}~^-]+(?:\\\\.[\\\\w!#$%&’*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\\\.)+[a-zA-Z]{2,6}$",
message = "Invalid email format")
private String email;
...
}
Как мы видим, все достаточно просто и наглядно.
Далее, нам необходимо модифицировать контроллеры и реализовать следующий функционал:
указать, что объект типа Student должен пройти валидацию;
получить результаты валидации объекта;
если объект не прошел валидацию - не добавлять объект в хранилище, выдать сообщение об ошибке в консоль.
Нам необходимо модифицировать метод контроллера, который обрабатывает данные формы. Указываем аннотацию @Valid, которая говорит о том, что полученный объект необходимо подвергнуть валидации. Далее указываем аргумент типа BindingResult, который хранит информацию о результате валидации. С помощью метода hasErrors() получаем результат валидации объекта.
@GetMapping("/")
public String addStudent(Model model) {
model.addAttribute("student", new Student());
return "index";
}
@PostMapping("/")
public String processAddStudentForm(@Valid Student student, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
System.out.println("Validation has been failed!");
return "index";
}
System.out.println(student);
list.add(student);
return "redirect:/";
}
При попытке отправить пустую форму, получаем сообщение в консоли
Последний шаг - необходимо предоставить пользователю информацию о том, что то или иное поле формы не прошло валидацию.
Самый простой способ проинформировать пользователь - показать сообщение об ошибке около поля, которое не прошло валидацию. Чтобы реализовать данный функционал, перейдем в шаблон index.html.
Рассмотрим поле "Фамилия". Сообщение об ошибке мы разместим снизу поля. Добавим соответствующий элемент <small> в HTML-макет.
Используем тег th:if. Если выражение внутри тега равно true, то элемент <small> будет показан на экране, если false - будет скрыт.
Выражение ${fields.hasErrors('lastName)} означает, есть ли ошибки валидации для поля lastName? Если ошибки есть - поле будет показано. Текст ошибки выводим с помощью атрибута th:errors.
Добавляем элементы для вывода ошибок для остальных полей формы. Проверяем результат
public class Student {
// Имя должно быть длиной от 2 до 50 символов
@Size(min = 2, max= 50, message = "First name should be from 2 to 50 characters")
private String firstName;
// Фамилия должна быть длиной от 2 до 50 символов
@Size(min = 2, max= 50, message = "Last name should be from 2 to 50 characters")
private String lastName;
// Возраст должен быть целым числом от 13 до 65
@Range(min = 13, max = 65, message = "Student age should be from 13 to 65 years")
private int age;
// Для валидации электронной почты используем регулярное выражение
@Pattern(regexp = "^[a-zA-Z0-9_!#$%&’*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$",
message = "Invalid email format")
private String email;
public Student(String firstName, String lastName, int age, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.email = email;
}
public Student() {
}
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
@Controller
public class StudentController {
private List<Student> list = new ArrayList<>();
@GetMapping("/")
public String addStudent(Model model) {
model.addAttribute("student", new Student());
return "index";
}
@PostMapping("/")
public String processAddStudentForm(@Valid Student student, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "index";
}
System.out.println(student);
list.add(student);
return "redirect:/";
}
}