Quando accettiamo gli input degli utenti in qualsiasi applicazione web, diventa necessario convalidarli. Possiamo convalidare l’input dell’utente lato client utilizzando JavaScript, ma è anche necessario convalidarlo lato server per assicurarci di elaborare dati validi nel caso in cui l’utente abbia JavaScript disabilitato.
Convalida di Spring
Il framework di Spring MVC supporta di default le specifiche JSR-303 e tutto ciò di cui abbiamo bisogno è aggiungere JSR-303 e le sue dipendenze di implementazione nell’applicazione Spring MVC. Spring fornisce anche l’annotazione @Validator
e la classe BindingResult
attraverso le quali possiamo ottenere gli errori generati dall’implementazione del Validator nel metodo del gestore delle richieste del controller. Possiamo creare le nostre implementazioni personalizzate del validatore in due modi: il primo è creare un’annotazione che rispetti le specifiche JSR-303 e implementare la sua classe Validator. Il secondo approccio consiste nell’implementare l’interfaccia org.springframework.validation.Validator
e impostarla come validatore nella classe del controller utilizzando l’annotazione @InitBinder
. Creiamo un semplice progetto Spring MVC in Spring Tool Suite in cui utilizzeremo le specifiche JSR-303 con l’artefatto di implementazione hibernate-validator. Utilizzeremo la validazione dei form basata su annotazioni e creeremo il nostro validatore personalizzato basato sulle specifiche JSR-303. Creeremo anche la nostra classe di validazione personalizzata implementando l’interfaccia Validator
e la utilizzeremo in uno dei metodi del gestore delle richieste del controller. Il nostro progetto finale è simile all’immagine sottostante. Analizziamo ciascuno dei componenti uno per uno.
Validatore dei moduli Spring MVC
Il nostro file pom.xml finale sarà simile a quanto segue. Oltre agli artefatti standard di Spring MVC, abbiamo le dipendenze validation-api e hibernate-validator nel progetto.
<?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>
Descrittore di distribuzione
Quando si crea un progetto Spring MVC da STS, vengono creati due file di configurazione dei contesti. Li ho puliti un po’ e ho solo un file di configurazione del bean di Spring. Il mio file web.xml finale sarà simile a quanto segue.
<?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>
File di configurazione dei bean di Spring
Di solito guardiamo agli innesti di Spring alla fine, ma questa volta non abbiamo molte configurazioni nel file di configurazione del bean di Spring. Il nostro file spring.xml finale sarà simile a quanto segue.
<?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>
L’unico punto importante da notare è il bean employeeValidator
che inietteremo in uno dei controller e il bean messageSource
per leggere i dati localizzati dai pacchetti di risorse. Il resto riguarda il supporto alle annotazioni, ai risolutori di visualizzazione e alla specifica del pacchetto da scansionare per le classi dei controller e altri componenti.
Classi Modello
In questo progetto abbiamo due classi modello: la prima in cui utilizzeremo l’annotazione JSR-303 e il nostro validatore basato su annotazioni personalizzato, e la seconda in cui utilizzeremo solo la nostra implementazione del validatore. Codice 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;
}
}
Notate che stiamo utilizzando le annotazioni @Email, @NotEmpty e @DateTimeFormat, che sono aggiuntive rispetto a JSR-303 e fornite dall’implementazione del validatore Hibernate. Alcune delle annotazioni JSR-303 che stiamo utilizzando sono @Size, @NotNull, ecc. L’annotazione @Phone che viene utilizzata è la nostra implementazione personalizzata basata sulle specifiche di JSR-303, la esamineremo nella sezione successiva. Codice 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;
}
}
L’Employee è un bean Java standard e utilizzeremo la nostra implementazione personalizzata del validatore per convalidare il modulo con il bean Employee.
Implementazioni personalizzate del validatore
Codice 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 {};
}
La maggior parte del codice è boilerplate code per conformarsi alle specifiche JSR-303. La parte più importante è l’annotazione @Constraint dove forniamo la classe che verrà utilizzata per la validazione, ovvero PhoneValidator
. Codice 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;
}
//valida i numeri di telefono nel formato "1234567890"
if (phoneNo.matches("\\d{10}")) return true;
//valida i numeri di telefono con -, . o spazi
else if(phoneNo.matches("\\d{3}[-\\.\\s]\\d{3}[-\\.\\s]\\d{4}")) return true;
//valida i numeri di telefono con una lunghezza di estensione compresa tra 3 e 5
else if(phoneNo.matches("\\d{3}-\\d{3}-\\d{4}\\s(x|(ext))\\d{3,5}")) return true;
//valida i numeri di telefono in cui il prefisso è tra parentesi ()
else if(phoneNo.matches("\\(\\d{3}\\)-\\d{3}-\\d{4}")) return true;
//restituisce false se l'input non corrisponde a nessuna delle opzioni
else return false;
}
}
La nostra implementazione del validatore JSR-303 dovrebbe implementare l’interfaccia javax.validation.ConstraintValidator
. Se stiamo utilizzando risorse come DataSource, possiamo inizializzarle nel metodo initialize()
. Il metodo di validazione è isValid
e restituisce true se i dati sono validi, altrimenti dovrebbe restituire false. Se sei nuovo alle espressioni regolari, puoi leggere ulteriori informazioni su Java Regular Expressions Tutorial. Codice della classe 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 {
//quali oggetti possono essere validati da questo validatore
@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 è l’implementazione del validatore specifico per Spring Framework. Il metodo supports()
viene implementato da Spring Framework per conoscere gli oggetti su cui può essere utilizzata questa validazione. Implementiamo il metodo validate()
e aggiungiamo gli errori se la validazione dei campi fallisce. Spring fornisce la classe di utilità org.springframework.validation.ValidationUtils
per le validazioni di base come null o vuoto. Una volta che questo metodo restituisce, il framework Spring associa l’oggetto Errors all’oggetto BindingResult che utilizziamo nel nostro metodo handler del controller. Nota che l’ultimo argomento di ValidationUtils.rejectIfEmptyOrWhitespace()
prende il nome chiave per le risorse dei messaggi. In questo modo possiamo fornire messaggi di errore localizzati all’utente. Per ulteriori informazioni sull’i18n in Spring, leggi Esempio di i18n in Spring.
Classi del Controller
Abbiamo due classi del controller, una per la validazione del modulo basata su annotazioni e un’altra per il nostro validatore personalizzato. Codice della classe 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";
}
}
Quando utilizziamo la convalida dei moduli basata su annotazioni, è sufficiente apportare piccole modifiche all’implementazione del metodo gestore del controller per farla funzionare. Innanzitutto, è necessario annotare l’oggetto modello che si desidera convalidare con l’annotazione @Valid
. Successivamente, è necessario avere un argomento BindingResult nel metodo, Spring si occupa di popolarlo con i messaggi di errore. La logica del metodo gestore è molto semplice, se ci sono errori, rispondiamo con la stessa pagina, altrimenti reindirizziamo l’utente alla pagina di successo. Un altro punto importante da notare è che stiamo aggiungendo l’attributo “customer” al modello, questo è necessario per far sapere al framework Spring quale oggetto modello utilizzare nella pagina del modulo. Se non lo facessimo, il binding dell’oggetto ai dati del modulo non avverrebbe e la nostra convalida del modulo non funzionerebbe. Codice della classe 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() {
// Il valore ModelAttribute deve essere lo stesso utilizzato in 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";
}
}
Per utilizzare un validatore personalizzato, innanzitutto è necessario iniettarlo nella classe del controller. Utilizziamo l’auto-wiring del bean Spring per realizzare ciò utilizzando le annotazioni @Autowired
e @Qualifier
. Successivamente, è necessario avere un metodo che accetti come argomento WebDataBinder e impostiamo il nostro validatore personalizzato da utilizzare. Questo metodo deve essere annotato con l’annotazione @InitBinder
. Utilizzare @ModelAttribute
è un altro modo per aggiungere il nostro oggetto bean al Modello. Il resto del codice è simile all’implementazione del controller del cliente.
Bundle di risorse per i messaggi di errore della validazione dei form
È ora di dare un’occhiata al nostro bundle di risorse in cui abbiamo diversi tipi di messaggi da utilizzare per gli errori di validazione. File message_en.properties:
# messaggi di errore definiti dall'applicazione
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
# messaggi di errore del framework Spring da utilizzare quando la conversione dai dati del form al bean non riesce
typeMismatch.int={0} Value must be an integer
typeMismatch.java.lang.Integer={0} must be an integer
typeMismatch={0} is of invalid format
# messaggi di errore dell'applicazione per le annotazioni, {ValidationClass}.{modelObjectName}.{field}
# {0} è il nome del campo, gli altri campi sono in ordine alfabetico, max e poi 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
# messaggi di classe di annotazione generica
Email=Email address is not valid
NotNull=This is a required field
NotEmpty=This is a required field
Past=Date should be Past
# annotazione di validazione personalizzata
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.
Pagine di visualizzazione con form e errori
Dato che stiamo utilizzando l’implementazione della validazione del framework Spring, dovremo utilizzare i tag Spring Form per ottenere gli errori e impostare il form bean e i nomi delle variabili. Il codice del nostro file custSave.jsp è riportato di seguito.
<%@ 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"
viene utilizzato per impostare il nome dell’attributo del modello sotto il quale l’oggetto del modulo è esposto. Il suo valore predefinito è “command” di default, quindi dovremmo impostarlo sul nome dell’attributo del modello che stiamo utilizzando nelle nostre classi controller. springForm:errors
viene utilizzato per visualizzare gli errori, se presenti, trovati durante il rendering della pagina. L’attributo path
viene utilizzato per definire la proprietà dell’oggetto da utilizzare per il binding dei dati. Il resto del codice è HTML standard con un po’ di CSS per lo stile dei messaggi di errore. Il nostro file custSaveSuccess.jsp è il seguente.
<%@ 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>
Pagina JSP semplice che mostra i valori del cliente se non ci sono errori di convalida e questa pagina viene restituita come risposta. Il suo nome è 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>
File 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>
Test dell’applicazione di convalida del modulo Spring MVC
La nostra applicazione è pronta per essere distribuita ed eseguire alcuni test, distribuiscila nel tuo servlet container preferito. Sto utilizzando Apache Tomcat 7 e le immagini seguenti mostrano alcune pagine con messaggi di errore di convalida. In base ai tuoi dati di input, potresti ottenere anche tu diversi messaggi di errore.
Questo è tutto per la convalida del modulo Spring MVC con diversi metodi e l’utilizzo di bundle di risorse per i messaggi di errore localizzati. Puoi scaricare il progetto di esempio dal link sottostante e sperimentare per saperne di più.
Source:
https://www.digitalocean.com/community/tutorials/spring-validation-example-mvc-validator