Валидация форм в Spring MVC
Last updated: 11 мая 2025 г.Валидация
– это проверка данных формы на то подходят ли они под какие-то условия.
Для начала необходимо скачать hibernate validator.
Можно скачать по ссылке https://hibernate.org/validator/releases/6.2/. Потом закидываем в lib jar файлы из папки dist и required.
Также давайте добавим две новые странички в проект. Так же как и в прошлом проекте, одна страница с формой, а другая, на которой пользователю будут выводиться значения, которые он ввел

Давайте теперь дополним класс SomeUser
. В этом классе создадим два новых поля и сгенерируем геттеры сеттеры для них. Эти новые поля будут связаны со своим текстовым полем в форме.
Содержимое этих полей будет валидироваться в соответствии с указанными аннотациями над этими полями.
То есть пользователь будет вводить значения в текстовые поля, после этого отправлять форму, в результате чего данные текстовых полей будут записываться в связанные с ними поля объекта в аттрибуте, далее содержимое полей в этом объекте помеченных аннотациями валидации будет собственно валидироваться, то есть проверяться соответствует ли то, что ввел пользователь в поля объекта тому, что может в нем быть, и если он ввел то, что в нем не может быть, ему выводиться сообщение о том, что он ввел что-то не так.
Итак разберем аннотации валидации:
1package classes;
2
3import java.util.LinkedHashMap;
4
5@Component
6public class SomeUser {
7
8 // Ниже используются аннотации валидации над полем.
9 // В нашем приложении текстовое поле формы будет связано
10 // с полем userName объекта в аттрибуте.
11 // Если поле помечено @NotNull значит оно будет проверяться
12 // на пустоту при отправке формы. То есть, если пользователь
13 // ничего не ввел в текстовое поле, которое связано с полем
14 // userName и отправил форму, то отправка формы не будет
15 // успешной, пока пользователь не введет значение
16 // в текстовое поле.
17 // message — это сообщение, которое будет
18 // показано пользователю, если он не ввел ничего в поле.
19 // С помощью @Size можно указать минимальное количество
20 // символов, которые пользователь должен ввести
21 // в текстовое поле.
22 @NotNull(message = "field is required!!!")
23 @Size(min = 5, message = "field is required!!!")
24 private String userName;
25
26 private String userCountry;
27 private String userLanguage;
28 private String[] userBrowser;
29
30 // Также форма будет содержать текстовое поле, которое
31 // будет связано с полем userAge объекта в атрибуте.
32 // С помощью @Min задаем минимальное число, которое
33 // можно указать в текстовом поле.
34 // С помощью @Max задаем максимальное число, которое
35 // можно указать в текстовом поле.
36 @Min(value = 0, message = "must be more than 0")
37 @Max(value = 100, message = "must be less than 100")
38 private Integer userAge;
39
40 // Также форма будет содержать текстовое поле, которое
41 // будет связано с полем userEmail объекта в атрибуте.
42 // С помощью @Pattern можно задать регулярное выражение,
43 // по которому будет проверяться содержимое текстового
44 // поля. Регулярные выражения мы пока не проходили.
45 // Но если вкратце, то это некоторое правило
46 // (оно может быть достаточно сложным), по которому
47 // валидируется содержимое поля.
48 // В нашем случае мы задали, что текстовое поле должно
49 // содержать 30 символов и может содержать
50 // такие-то символы.
51 @Pattern(regexp = "^[a-zA-Z0-9]{30}", message = "must be 30 characters")
52 private String userEmail;
53
54 public SomeUser() { }
55
56 public String getUserName() {
57 return userName;
58 }
59
60 public void setUserName(String userName) {
61 this.userName = userName;
62 }
63
64 public String getUserCountry() {
65 return userCountry;
66 }
67
68 public void setUserCountry(String userCountry) {
69 this.userCountry = userCountry;
70 }
71
72 public String getUserLanguage() {
73 return userLanguage;
74 }
75
76 public void setUserLanguage(String userLanguage) {
77 this.userLanguage = userLanguage;
78 }
79
80 public String[] getUserBrowser() {
81 return userBrowser;
82 }
83
84 public void setUserBrowser(String[] userBrowser) {
85 this.userBrowser = userBrowser;
86 }
87
88 public Integer getUserAge() {
89 return userAge;
90 }
91
92 public void setUserAge(Integer userAge) {
93 this.userAge = userAge;
94 }
95
96 public String getUserEmail() {
97 return userEmail;
98 }
99
100 public void setUserEmail(String userEmail) {
101 this.userEmail = userEmail;
102 }
103}
Давайте теперь свяжем новые поля в объекте в аттрибуте username
c новыми тегами в форме на странице. Также с помощью тега form:errors
будут выводиться сообщения, которые мы писали в message в классе у полей. Этот тег пишем там, где должно появляться это сообщение на странице.
Страница с формой:
1<%@ page language="java" contentType="text/html;
2 charset=ISO-8859-1"
3 pageEncoding="ISO-8859-1"%>
4<%@ taglib prefix="form"
5 uri="http://www.springframework.org/tags/form"%>
6<%@ page isELIgnored="false" %>
7<!DOCTYPE html>
8<html>
9<head>
10<meta charset="ISO-8859-1">
11<title>Insert title here</title>
12<style>.ErrorClass{color:blue}</style>
13</head>
14<body>
15<form:form action="FormValidProcessor" modelAttribute="someuser">
16 username: <form:input path="userName"/>
17 <!-- form:errors - тег сообщения об ошибке если ввели не
18 правильные данные. в path переменная (точнее часть имени
19 геттера сеттера переменной как мы помним) в аттребуте, к
20 которой применяется валидация.
21 cssClass - оформление сообщения об ошибке. То есть как то что
22 мы писали в message (а там как мы помним мы писали сообщение
23 об ошибке) в классе SomeUser будет оформлено. ErrorClass
24 это имя css класса его можно найти выше в теге style. -->
25 <form:errors path="userName" cssClass="ErrorClass"/> <br/>
26 <!-- для min, max аннотаций. -->
27 Age: <form:input path="userAge"/>
28 <form:errors path="userAge" cssClass="ErrorClass"/> <br/>
29 <!-- для pattern аннотаций для регулярных выражений. -->
30 Email: <form:input path="userEmail"/>
31 <form:errors path="userEmail" cssClass="ErrorClass"/> <br/>
32 <input type="submit" value="submit"/> <br/>
33</form:form>
34</body>
35</html>
Как и в прошлом уроке, создадим два обработчика. Один для перехода на страницу с формой, другой же будет в зависимости от того ввел пользователь валидные данные или нет либо переводить пользователя обратно на страницу с формой, либо перенаправлять его на страницу на которой будет отображено пользователю то, что он вводил в поля.
1package classes;
2
3import javax.servlet.http.HttpServletRequest;
4
5@Controller
6@RequestMapping("/FirstController")
7public class MVCcontroller {
8
9 @RequestMapping("/FirstJSP")
10 public String FirstJSP() {
11 return "JSPpage";
12 }
13
14 @RequestMapping("/SecondJSP")
15 public String SecondJSP() {
16 return "JSPpage1";
17 }
18
19 @RequestMapping("/FormPage")
20 public String FormPage() {
21 return "FormPage";
22 }
23
24 @RequestMapping("/FormProcessingController")
25 public String FormProcessingController(
26 HttpServletRequest req, Model model) {
27 model.addAttribute("resposeMsg",
28 (req.getParameter("username") + " entered!"));
29 return "FormProcessingPage";
30 }
31
32 @RequestMapping("/FormTagPage")
33 public String FormTagPage(Model model) {
34 model.addAttribute("someuser", new SomeUser());
35 return "FormTagPage";
36 }
37
38 @RequestMapping("/FormTagProcessor")
39 public String FormTagProcessor(
40 @ModelAttribute("username") SomeUser someUser) {
41 System.out.println(someUser.getUserName());
42 System.out.println(someUser.getUserCountry());
43 System.out.println(someUser.getUserLanguage());
44 System.out.println(someUser.getUserBrowser());
45 return "FormTagProcessingPage";
46 }
47
48 // Новый обработчик
49 // он просто переводит на страницу с формой,
50 // которая будет валидироваться.
51 @RequestMapping("/FormValidPage")
52 public String FormValidPage(Model model) {
53 model.addAttribute("someuser", new SomeUser());
54 return "FormValidPage";
55 }
56
57 // Новый обработчик
58 @RequestMapping("/FormValidProcessor")
59 // аннотацией @Valid указываем что пришедший атрибут
60 // из формы в обработчик подлежит валидации и в нем
61 // будут проверены поля с аннотациями валидации
62 public String FormValidProcessor(
63 @Valid @ModelAttribute("someuser") SomeUser someUser,
64 BindingResult mybindingResult) {
65 // Результат же валидации атрибута
66 // записывается в mybindingResult.
67
68 // проверяем bindingResult на наличие ошибок валидации
69 if (mybindingResult.hasErrors()) {
70 // если есть ошибки валидации отправляем уже
71 // валидированный атрибут обратно в форму где
72 // ошибка валидации будет отображена тегом form:errors
73 return "FormValidPage";
74 } else {
75 // если их нет то отправляем атрибут
76 // на результирующую страницу где из него
77 // выведем содержимое нужной переменной
78 return "FormValidProcessingPage";
79 }
80 }
81}
На странице на которую перенаправляет пользователя обработчик (если данные в объекте из аттрибута оказались валидными) извлечем выбранные пользователем значения из объекта в аттрибуте username
.
1<%@ page language="java" contentType="text/html;
2 charset=ISO-8859-1"
3 pageEncoding="ISO-8859-1"%>
4<%@ page isELIgnored="false"%>
5<!DOCTYPE html>
6<html>
7<head>
8 <title>Auth Form</title>
9</head>
10<body>
11 <h2>${someuser.userName}</h2>
12 <h2>${someuser.userAge}</h2>
13 <h2>${someuser.userEmail}</h2>
14</body>
15</html>
Перейдем на страницу с формой через обработчик по пути /FormValidPage
. Первое текстовое поле давайте оставим пустым, во втором введем число 144, в третьем введем меньше 30 символов.
и после нажатия Submit:

Видим, что вывелись сообщения, которые мы писали в message в аннотациях о том, что пользователь ввел неверные данные. О том, что пользователь оставил поле пустым, а оно не должно быть пустым, о том, что он ввел число выше ста и о том, что поле должно содержать ровно 30 символов.
То есть очевидно аннотации NotNull
, Max
и Pattern
работают.
Давайте теперь проверим аннотации Size
и Min
. Введем в перовое поле меньше 5 символов, а во второе поле число меньше 0.
После нажатия Submit:

Видим, что сообщения, которые мы писали в аннотациях Size
и Min
вывелись. Значит, что аннотации работают.
Теперь давайте введем правильные данные, то есть в перове поле больше 5 букв, во второе поле число между 0 и 100, в третье поле ровно 30 символов.
Вот так:

Нажимаем Submit:

Как видим, обработчик успешно перевел нас на вторую страницу и отобразил на ней введенные данные поскольку введенные данные были валидными.
Это были основные аннотации валидации. Есть и другие конечно.
Также можно создавать еще и свои собственные аннотации валидации. Умение их создавать тоже может пригодиться, но в принципе в большинстве случаев свою какую-то сложную валидацию можно задать с помощью регулярных выражений, поэтому не будем заострять внимание.
Следующие уроки
Введение в ORM с использованием Hibernate
20
мин.
Обзор языка запросов HQL в Hibernate
17
мин.
HQL: обновление данных (Update)
16
мин.