Когда мы принимаем ввод пользователя в любом веб-приложении, становится необходимым его валидировать. Мы можем провести валидацию ввода пользователя на стороне клиента с использованием JavaScript, но также важно провести валидацию на стороне сервера, чтобы убедиться, что мы обрабатываем действительные данные в случае отключенного JavaScript у пользователя.
Spring Validation
Spring MVC Framework поддерживает спецификации JSR-303 по умолчанию, и все, что нам нужно сделать, это добавить зависимости JSR-303 и ее реализации в приложение Spring MVC. Spring также предоставляет аннотацию @Validator
и класс BindingResult
, через которые мы можем получить ошибки, возникшие при реализации валидатора в методе обработчика запросов контроллера. Мы можем создавать собственные реализации валидаторов двумя способами: первый – создать аннотацию, соответствующую спецификациям JSR-303, и реализовать ее класс валидатора. Второй подход – реализовать интерфейс org.springframework.validation.Validator
и установить его в качестве валидатора в классе Controller, используя аннотацию @InitBinder
. Давайте создадим простой проект Spring MVC в Spring Tool Suite, где мы будем использовать спецификации JSR-303 с артефактом ее реализации hibernate-validator. Мы будем использовать аннотационную проверку формы и создадим собственный валидатор на основе стандартов JSR-303. Мы также создадим собственный класс валидатора, реализуя интерфейс Validator
, и будем использовать его в одном из методов обработчика контроллера. Наш конечный проект выглядит как на изображении ниже. Давайте рассмотрим каждый из компонентов по очереди.
Spring MVC Форма Валидатор
Наш окончательный файл pom.xml выглядит следующим образом. Помимо стандартных артефактов Spring MVC, у нас есть зависимости от validation-api и hibernate-validator в проекте.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev</groupId>
<artifactId>spring</artifactId>
<name>SpringFormValidation</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.7</java-version>
<org.springframework-version>4.0.2.RELEASE</org.springframework-version>
<org.aspectj-version>1.7.4</org.aspectj-version>
<org.slf4j-version>1.7.5</org.slf4j-version>
</properties>
<dependencies>
<!-- Form Validation using Annotations -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.1.0.Final</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
Файл развёртывания
Когда вы создаёте проект Spring MVC из STS, он создаёт два файла конфигурации контекста. Я немного его очистил и оставил только один файл конфигурации бина Spring. Мой окончательный файл web.xml выглядит следующим образом.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/spring.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Файл конфигурации бинов Spring
Обычно мы смотрим на проводки spring в последнюю очередь, но на этот раз у нас нет множества конфигураций в файле конфигурации бина Spring. Наш окончательный файл spring.xml выглядит следующим образом.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<beans:bean id="employeeValidator" class="com.journaldev.spring.form.validator.EmployeeFormValidator" />
<beans:bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basename" value="classpath:message" />
<beans:property name="defaultEncoding" value="UTF-8" />
</beans:bean>
<context:component-scan base-package="com.journaldev.spring" />
</beans:beans>
Единственный важный момент, который следует отметить, это бин employeeValidator
, который мы внедрим в один из контроллеров, и бин messageSource
для чтения локализованных данных из файлов свойств. Остальная часть предназначена для поддержки аннотаций, резолверов представлений и предоставления пакета для сканирования классов контроллеров и других компонентов.
Классы моделей
У нас есть два класса моделей в этом проекте – первый, где мы будем использовать аннотацию JSR-303 и нашу собственную аннотацию на основе валидатора, и второй, где мы будем использовать только нашу реализацию валидатора. Код Customer.java:
package com.journaldev.spring.form.model;
import java.util.Date;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
import com.journaldev.spring.form.validator.Phone;
public class Customer {
@Size(min=2, max=30)
private String name;
@NotEmpty @Email
private String email;
@NotNull @Min(18) @Max(100)
private Integer age;
@NotNull
private Gender gender;
@DateTimeFormat(pattern="MM/dd/yyyy")
@NotNull @Past
private Date birthday;
@Phone
private String phone;
public enum Gender {
MALE, FEMALE
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
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;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
Обратите внимание, что мы используем аннотации @Email, @NotEmpty и @DateTimeFormat, которые дополнительны к JSR-303 и предоставлены реализацией валидатора Hibernate. Некоторые из аннотаций JSR-303, которые мы используем, – @Size, @NotNull и т. д. Аннотация @Phone, которую мы используем, – это наша собственная реализация на основе спецификаций JSR-303, мы рассмотрим это в следующем разделе. Код Employee.java:
package com.journaldev.spring.form.model;
public class Employee {
private int id;
private String name;
private String role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
Employee – это стандартный java bean, и мы будем использовать нашу собственную реализацию валидатора для проверки формы с бином Employee.
Пользовательские реализации валидатора
Код Phone.java:
package com.journaldev.spring.form.validator;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import javax.validation.Constraint;
import javax.validation.Payload;
@Documented
@Constraint(validatedBy = PhoneValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Phone {
String message() default "{Phone}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Большая часть кода представляет собой образцовый код для соответствия спецификациям JSR-303. Самая важная часть – аннотация @Constraint, где мы указываем класс, который будет использоваться для валидации, т.е. PhoneValidator
. Код PhoneValidator.java:
package com.journaldev.spring.form.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class PhoneValidator implements ConstraintValidator {
@Override
public void initialize(Phone paramA) {
}
@Override
public boolean isValid(String phoneNo, ConstraintValidatorContext ctx) {
if(phoneNo == null){
return false;
}
//validate phone numbers of format "1234567890"
if (phoneNo.matches("\\d{10}")) return true;
//validating phone number with -, . or spaces
else if(phoneNo.matches("\\d{3}[-\\.\\s]\\d{3}[-\\.\\s]\\d{4}")) return true;
//validating phone number with extension length from 3 to 5
else if(phoneNo.matches("\\d{3}-\\d{3}-\\d{4}\\s(x|(ext))\\d{3,5}")) return true;
//validating phone number where area code is in braces ()
else if(phoneNo.matches("\\(\\d{3}\\)-\\d{3}-\\d{4}")) return true;
//return false if nothing matches the input
else return false;
}
}
Наша реализация валидатора спецификаций JSR-303 должна реализовывать интерфейс javax.validation.ConstraintValidator
. Если мы используем какие-либо ресурсы, такие как DataSource, мы можем инициализировать их в методе initialize()
. Метод валидации – isValid
, который возвращает true, если данные допустимы, иначе он должен возвращать false. Если вы новичок в регулярных выражениях, вы можете узнать больше об этом в Руководстве по регулярным выражениям Java. Код класса EmployeeFormValidator.java:
package com.journaldev.spring.form.validator;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import com.journaldev.spring.form.model.Employee;
public class EmployeeFormValidator implements Validator {
//which objects can be validated by this validator
@Override
public boolean supports(Class > paramClass) {
return Employee.class.equals(paramClass);
}
@Override
public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "id", "id.required");
Employee emp = (Employee) obj;
if(emp.getId() <=0){
errors.rejectValue("id", "negativeValue", new Object[]{"'id'"}, "id can't be negative");
}
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "name.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "role", "role.required");
}
}
EmployeeFormValidator – это реализация валидатора, специфичная для Spring Framework. Метод supports()
реализуется Spring Framework для определения объектов, на которых можно использовать эту валидацию. Мы реализуем метод validate()
и добавляем ошибки, если не проходит валидация какого-либо поля. Spring предоставляет утилитарный класс org.springframework.validation.ValidationUtils
для базовых проверок, таких как null или пустота. После завершения этого метода, Spring Framework привязывает объект Errors к объекту BindingResult, который мы используем в методе обработчика контроллера. Обратите внимание, что последний аргумент метода ValidationUtils.rejectIfEmptyOrWhitespace()
принимает ключ для сообщений ресурсов. Таким образом, мы можем предоставлять локализованные сообщения об ошибках пользователю. Для получения дополнительной информации об i18n в Spring читайте Пример i18n в Spring.
Классы контроллеров
У нас есть два класса контроллеров, один для аннотационной валидации формы и другой для нашего собственного валидатора. Код класса CustomerController.java:
package com.journaldev.spring.form.controllers;
import java.util.HashMap;
import java.util.Map;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.journaldev.spring.form.model.Customer;
@Controller
public class CustomerController {
private static final Logger logger = LoggerFactory
.getLogger(CustomerController.class);
private Map<String, Customer> customers = null;
public CustomerController(){
customers = new HashMap<String, Customer>();
}
@RequestMapping(value = "/cust/save", method = RequestMethod.GET)
public String saveCustomerPage(Model model) {
logger.info("Returning custSave.jsp page");
model.addAttribute("customer", new Customer());
return "custSave";
}
@RequestMapping(value = "/cust/save.do", method = RequestMethod.POST)
public String saveCustomerAction(
@Valid Customer customer,
BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
logger.info("Returning custSave.jsp page");
return "custSave";
}
logger.info("Returning custSaveSuccess.jsp page");
model.addAttribute("customer", customer);
customers.put(customer.getEmail(), customer);
return "custSaveSuccess";
}
}
Когда мы используем валидацию формы на основе аннотаций, нам просто нужно внести небольшие изменения в реализацию метода обработчика контроллера, чтобы заставить ее работать. Сначала нам нужно аннотировать объект модели, который мы хотим валидировать, с помощью аннотации @Valid
. Затем нам нужно иметь аргумент BindingResult в методе, и Spring заботится о его заполнении сообщениями об ошибках. Логика метода обработчика очень проста: если есть ошибки, мы отвечаем той же страницей, в противном случае мы перенаправляем пользователя на страницу успеха. Еще один важный момент: мы добавляем атрибут “customer” к модели, это необходимо, чтобы Spring framework знал, какой объект модели использовать на странице формы. Если мы этого не сделаем, привязка объекта к данным формы не произойдет, и наша валидация формы не будет работать. Код класса EmployeeController.java:
package com.journaldev.spring.form.controllers;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.journaldev.spring.form.model.Employee;
@Controller
public class EmployeeController {
private static final Logger logger = LoggerFactory
.getLogger(EmployeeController.class);
private Map emps = null;
@Autowired
@Qualifier("employeeValidator")
private Validator validator;
@InitBinder
private void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
public EmployeeController() {
emps = new HashMap();
}
@ModelAttribute("employee")
public Employee createEmployeeModel() {
// Значение ModelAttribute должно быть таким же, как используется в empSave.jsp
return new Employee();
}
@RequestMapping(value = "/emp/save", method = RequestMethod.GET)
public String saveEmployeePage(Model model) {
logger.info("Returning empSave.jsp page");
return "empSave";
}
@RequestMapping(value = "/emp/save.do", method = RequestMethod.POST)
public String saveEmployeeAction(
@ModelAttribute("employee") @Validated Employee employee,
BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
logger.info("Returning empSave.jsp page");
return "empSave";
}
logger.info("Returning empSaveSuccess.jsp page");
model.addAttribute("emp", employee);
emps.put(employee.getId(), employee);
return "empSaveSuccess";
}
}
Для использования пользовательского валидатора сначала нам нужно внедрить его в класс контроллера. Мы используем автоматическую проводку бина Spring для достижения этого с использованием аннотаций @Autowired
и @Qualifier
. Затем нам нужен метод, который примет WebDataBinder в качестве аргумента, и мы устанавливаем наш пользовательский валидатор для использования. Этот метод должен быть аннотирован аннотацией @InitBinder
. Использование @ModelAttribute
– еще один способ добавить наш объект бина в модель. Остальной код аналогичен реализации контроллера клиента.
Набор ресурсов сообщений об ошибках валидации формы
Пора взглянуть на наш набор ресурсов, в котором содержатся различные типы сообщений, используемых для отображения ошибок валидации. Файл message_en.properties:
#application defined error messsages
id.required=Employee ID is required
name.required=Employee Name is required
role.required=Employee Role is required
negativeValue={0} can't be negative or zero
#Spring framework error messages to be used when conversion from form data to bean fails
typeMismatch.int={0} Value must be an integer
typeMismatch.java.lang.Integer={0} must be an integer
typeMismatch={0} is of invalid format
#application messages for annotations, {ValidationClass}.{modelObjectName}.{field}
#the {0} is field name, other fields are in alphabatical order, max and then min
Size.customer.name=Customer {0} should be between {2} and {1} characters long
NotEmpty.customer.email=Email is a required field
NotNull.customer.age=Customer {0} should be in years
#Generic annotation class messages
Email=Email address is not valid
NotNull=This is a required field
NotEmpty=This is a required field
Past=Date should be Past
#Custom validation annotation
Phone=Invalid format, valid formats are 1234567890, 123-456-7890 x1234
I have provided message key details in the comment itself, so I will skip them here. The only important point to note here is the way messages will be looked up, first key name {ValidationClass}.{modelObjectName}.{field} is looked up and if that is not found then {ValidationClass}.{modelObjectName} is looked up. If that is missing, then finally {ValidationClass} key is looked up. If nothing is found then the default message provided will be returned. Read more about resource messages at Spring Localization Example.
Страницы просмотра с формой и ошибками
Поскольку мы используем реализацию валидации Spring framework, нам придется использовать теги Spring Form, чтобы получить ошибки и установить форму бина и имена переменных. Ниже приведен код нашего файла custSave.jsp.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="https://www.springframework.org/tags/form"
prefix="springForm"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Customer Save Page</title>
<style>
.error {
color: #ff0000;
font-style: italic;
font-weight: bold;
}
</style>
</head>
<body>
<springForm:form method="POST" commandName="customer"
action="save.do">
<table>
<tr>
<td>Name:</td>
<td><springForm:input path="name" /></td>
<td><springForm:errors path="name" cssClass="error" /></td>
</tr>
<tr>
<td>Email:</td>
<td><springForm:input path="email" /></td>
<td><springForm:errors path="email" cssClass="error" /></td>
</tr>
<tr>
<td>Age:</td>
<td><springForm:input path="age" /></td>
<td><springForm:errors path="age" cssClass="error" /></td>
</tr>
<tr>
<td>Gender:</td>
<td><springForm:select path="gender">
<springForm:option value="" label="Select Gender" />
<springForm:option value="MALE" label="Male" />
<springForm:option value="FEMALE" label="Female" />
</springForm:select></td>
<td><springForm:errors path="gender" cssClass="error" /></td>
</tr>
<tr>
<td>Birthday:</td>
<td><springForm:input path="birthday" placeholder="MM/dd/yyyy"/></td>
<td><springForm:errors path="birthday" cssClass="error" /></td>
</tr>
<tr>
<td>Phone:</td>
<td><springForm:input path="phone" /></td>
<td><springForm:errors path="phone" cssClass="error" /></td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="Save Customer"></td>
</tr>
</table>
</springForm:form>
</body>
</html>
commandName="customer"
используется для установки имени атрибута модели, под которым представлен объект формы. Его значение по умолчанию – «command», поэтому мы должны установить его в имя атрибута модели, которое мы используем в наших классах контроллеров. springForm:errors
используется для отображения ошибок, если они есть, когда страница отображается. Атрибут path
используется для определения свойства объекта, которое будет использоваться для привязки данных. Остальной код представляет собой стандартный HTML с некоторыми CSS для стилизации сообщений об ошибках. Наш файл custSaveSuccess.jsp приведен ниже.
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fmt" uri="https://java.sun.com/jsp/jstl/fmt" %>
<%@ page session="false" %>
<html>
<head>
<title>Customer Saved Successfully</title>
</head>
<body>
<h3>
Customer Saved Successfully.
</h3>
<strong>Customer Name:${customer.name}</strong><br>
<strong>Customer Email:${customer.email}</strong><br>
<strong>Customer Age:${customer.age}</strong><br>
<strong>Customer Gender:${customer.gender}</strong><br>
<strong>Customer Birthday:<fmt:formatDate value="${customer.birthday}" type="date" /></strong><br>
</body>
</html>
Простая JSP-страница, отображающая значения клиента, если ошибок валидации нет, и эта страница возвращается в качестве ответа. Ее имя – empSave.jsp.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="https://www.springframework.org/tags/form"
prefix="springForm"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Employee Save Page</title>
<style>
.error {
color: #ff0000;
font-style: italic;
font-weight: bold;
}
</style>
</head>
<body>
<springForm:form method="POST" commandName="employee"
action="save.do">
<table>
<tr>
<td>Employee ID:</td>
<td><springForm:input path="id" /></td>
<td><springForm:errors path="id" cssClass="error" /></td>
</tr>
<tr>
<td>Employee Name:</td>
<td><springForm:input path="name" /></td>
<td><springForm:errors path="name" cssClass="error" /></td>
</tr>
<tr>
<td>Employee Role:</td>
<td><springForm:select path="role">
<springForm:option value="" label="Select Role" />
<springForm:option value="ceo" label="CEO" />
<springForm:option value="developer" label="Developer" />
<springForm:option value="manager" label="Manager" />
</springForm:select></td>
<td><springForm:errors path="role" cssClass="error" /></td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="Save"></td>
</tr>
</table>
</springForm:form>
</body>
</html>
Файл empSaveSuccess.jsp:
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Employee Saved Successfully</title>
</head>
<body>
<h3>
Employee Saved Successfully.
</h3>
<strong>Employee ID:${emp.id}</strong><br>
<strong>Employee Name:${emp.name}</strong><br>
<strong>Employee Role:${emp.role}</strong><br>
</body>
</html>
Протестируйте приложение валидации форм Spring MVC
Наше приложение готово к развертыванию и запуску некоторых тестов, разверните его в вашем любимом контейнере сервлетов. Я использую Apache Tomcat 7, и ниже показаны некоторые страницы с сообщениями об ошибках валидации. Исходя из ваших входных данных, вы также можете получить разные сообщения об ошибках.
Вот и все для валидации форм Spring MVC различными способами и использования ресурсных пакетов для локализованных сообщений об ошибках. Вы можете загрузить образец проекта по ссылке ниже и поиграться с ним, чтобы узнать больше.
Source:
https://www.digitalocean.com/community/tutorials/spring-validation-example-mvc-validator