Spring-Validierungsbeispiel – Spring MVC-Formularüberprüfer

Wenn wir Benutzereingaben in einer Webanwendung akzeptieren, wird es notwendig, sie zu validieren. Wir können die Benutzereingabe auf der Clientseite mit JavaScript validieren, aber es ist auch erforderlich, sie auf der Serverseite zu validieren, um sicherzustellen, dass wir gültige Daten verarbeiten, falls der Benutzer JavaScript deaktiviert hat.

Spring Validation

Das Spring MVC Framework unterstützt standardmäßig die JSR-303 Spezifikationen, und alles, was wir tun müssen, ist, JSR-303 und seine Implementierungsabhängigkeiten in der Spring MVC-Anwendung hinzuzufügen. Spring bietet auch die Annotation @Validator und die Klasse BindingResult, über die wir die von der Validator-Implementierung im Controller-Anforderungs-Handler-Methoden ausgelösten Fehler erhalten können. Wir können unsere benutzerdefinierten Validator-Implementierungen auf zwei Arten erstellen: Die erste besteht darin, eine Annotation zu erstellen, die den JSR-303 Spezifikationen entspricht, und ihre Validator-Klasse zu implementieren. Der zweite Ansatz besteht darin, das Interface org.springframework.validation.Validator zu implementieren und es als Validator in der Controller-Klasse mithilfe der Annotation @InitBinder festzulegen. Lassen Sie uns ein einfaches Spring MVC-Projekt in der Spring Tool Suite erstellen, in dem wir JSR-303 Spezifikationen mit ihrem Implementierungsartefakt hibernate-validator verwenden. Wir werden die formularbasierte Validierung von Annotationen verwenden und unseren eigenen benutzerdefinierten Validator gemäß den Standards der JSR-303 Spezifikationen erstellen. Außerdem werden wir unsere eigene benutzerdefinierte Validator-Klasse erstellen, indem wir das Interface Validator implementieren und es in einer der Controller-Handler-Methoden verwenden. Unser endgültiges Projekt sieht wie das folgende Bild aus. Lassen Sie uns nun jeden der Komponenten einzeln betrachten.

Spring MVC Form Validator

Unsere abschließende pom.xml-Datei sieht wie folgt aus. Abgesehen von den Standard-Spring-MVC-Artefakten haben wir validation-api- und hibernate-validator-Abhängigkeiten im Projekt.

<?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>

Bereitstellungsbeschreibung

Wenn Sie ein Spring-MVC-Projekt von STS aus erstellen, werden zwei Kontextkonfigurationsdateien erstellt. Ich habe es etwas aufgeräumt und habe nur eine Spring-Bean-Konfigurationsdatei. Meine abschließende web.xml-Datei sieht wie folgt aus.

<?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 Bean-Konfigurationsdatei

Normalerweise schauen wir uns das Spring-Wiring zuletzt an, aber dieses Mal haben wir nicht viele Konfigurationen in der Spring-Bean-Konfigurationsdatei. Unsere abschließende spring.xml-Datei sieht wie folgt aus.

<?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>

Der einzige wichtige Punkt ist, dass das employeeValidator-Bean, das wir in einen der Controller injizieren werden, und das messageSource-Bean, um lokalisierte Daten aus Ressourcenbündeln zu lesen. Der Rest dient zur Unterstützung von Annotationen, View-Resolvern und zum Bereitstellen des zu durchsuchenden Pakets für Controller-Klassen und andere Komponenten.

Modell Klassen

Wir haben zwei Modellklassen in diesem Projekt – die erste, in der wir die JSR-303 Annotation und unseren benutzerdefinierten Annotations basierten Validierer verwenden werden und die zweite, in der wir nur unsere Validator Implementierung verwenden werden. Kunden.java Code:

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;
	}
	
}

Beachten Sie, dass wir @Email, @NotEmpty und @DateTimeFormat Annotationen verwenden, die zusätzlich zu JSR-303 und von der Hibernate-Validator-Implementierung bereitgestellt werden. Einige der JSR-303-Annotationen, die wir verwenden, sind @Size, @NotNull, etc. Die verwendete @Phone Annotation ist unsere benutzerdefinierte Implementierung basierend auf den JSR-303 Spezifikationen, wir werden dies im nächsten Abschnitt näher betrachten. Mitarbeiter.java Code:

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;
	}
	
}

Der Mitarbeiter ist eine Standard-Java-Bean und wir werden unsere benutzerdefinierte Validator-Implementierung verwenden, um das Formular mit der Mitarbeiter-Bean zu validieren.

Benutzerdefinierte Validator Implementierungen

Telefon.java Code:

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 {};
      
}

Der größte Teil ist Boilerplate-Code, um den JSR-303-Spezifikationen zu entsprechen. Der wichtigste Teil ist die @Constraint-Annotation, in der wir die Klasse angeben, die für die Validierung verwendet wird, d. h. PhoneValidator. Der Code in PhoneValidator.java lautet:

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;
		}
		//Telefonnummern im Format "1234567890" validieren
        if (phoneNo.matches("\\d{10}")) return true;
        //Telefonnummer mit -, . oder Leerzeichen validieren
        else if(phoneNo.matches("\\d{3}[-\\.\\s]\\d{3}[-\\.\\s]\\d{4}")) return true;
        //Telefonnummer mit einer Erweiterungslänge von 3 bis 5 validieren
        else if(phoneNo.matches("\\d{3}-\\d{3}-\\d{4}\\s(x|(ext))\\d{3,5}")) return true;
        //Telefonnummer validieren, bei der die Vorwahl in Klammern steht ()
        else if(phoneNo.matches("\\(\\d{3}\\)-\\d{3}-\\d{4}")) return true;
        //false zurückgeben, wenn nichts mit der Eingabe übereinstimmt
        else return false;
	}

}

Unsere JSR-303-Spezifikationsvalidierungsimplementierung sollte das javax.validation.ConstraintValidator-Interface implementieren. Wenn wir Ressourcen wie DataSource verwenden, können wir sie in der Methode initialize() initialisieren. Die Validierungsmethode ist isValid und gibt true zurück, wenn die Daten gültig sind, andernfalls sollte sie false zurückgeben. Wenn Sie neu in regulären Ausdrücken sind, können Sie mehr darüber unter Java Regular Expressions Tutorial erfahren. Der Code der Klasse EmployeeFormValidator.java lautet:

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 {

	//welche Objekte von diesem Validator validiert werden können
	@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 ist die Validator-Implementierung, die spezifisch für das Spring Framework ist. Die Methode supports() wird von Spring Framework implementiert, um zu wissen, auf welchen Objekten diese Validierung verwendet werden kann. Wir implementieren die Methode validate() und fügen Fehler hinzu, wenn eine Feldvalidierung fehlschlägt. Spring bietet die Utility-Klasse org.springframework.validation.ValidationUtils für grundlegende Validierungen wie null oder leer an. Sobald diese Methode zurückkehrt, bindet das Spring Framework das Errors-Objekt an das BindingResult-Objekt, das wir in unserer Controller-Handlermethode verwenden. Beachten Sie, dass das letzte Argument von ValidationUtils.rejectIfEmptyOrWhitespace() den Schlüsselnamen für Nachrichtenressourcen übernimmt. Auf diese Weise können wir lokalisierte Fehlermeldungen für den Benutzer bereitstellen. Weitere Informationen zur Internationalisierung in Spring finden Sie unter Spring i18n Beispiel.

Controller-Klassen

Wir haben zwei Controller-Klassen, eine für die Annotation-basierte Formularvalidierung und eine weitere für unseren benutzerdefinierten Validator. Der Code der Klasse 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";
	}

}

Wenn wir die formularbasierte Validierung mithilfe von Annotationen verwenden, müssen wir nur geringfügige Änderungen an der Implementierung unserer Controller-Handler-Methode vornehmen, damit sie funktioniert. Zuerst müssen wir das Modellobjekt, das wir validieren möchten, mit der @Valid-Annotation kennzeichnen. Dann benötigen wir ein BindingResult-Argument in der Methode. Spring kümmert sich darum, es mit Fehlermeldungen zu füllen. Die Logik der Handler-Methode ist sehr einfach: Wenn Fehler vorhanden sind, antworten wir mit derselben Seite, ansonsten leiten wir den Benutzer zur Erfolgsseite weiter. Ein weiterer wichtiger Punkt ist, dass wir das Attribut „customer“ dem Modell hinzufügen. Dies ist notwendig, damit das Spring-Framework weiß, welches Modellobjekt auf der Formularseite verwendet werden soll. Wenn wir dies nicht tun, findet keine Bindung des Objekts an die Formulardaten statt und unsere Formularvalidierung funktioniert nicht. Der Code der Klasse 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() {
		// Der Wert von ModelAttribute sollte mit dem in empSave.jsp verwendeten übereinstimmen
		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";
	}
}

Um einen benutzerdefinierten Validator zu verwenden, müssen wir ihn zuerst in der Controller-Klasse injizieren. Wir verwenden Spring Bean Autoverdrahtung, um dies mit den Annotationen @Autowired und @Qualifier zu erreichen. Als nächstes benötigen wir eine Methode, die einen WebDataBinder als Argument entgegennimmt, und setzen unseren benutzerdefinierten Validator, der verwendet werden soll. Diese Methode sollte mit der Annotation @InitBinder versehen sein. Die Verwendung von @ModelAttribute ist eine weitere Möglichkeit, unser Bean-Objekt zum Modell hinzuzufügen. Der restliche Code ähnelt der Implementierung des Kundencontrollers.

Formularvalidierungsfehlermeldungen Ressourcenbündel

Es ist an der Zeit, unser Ressourcenbündel zu betrachten, in dem wir verschiedene Arten von Nachrichten für Validierungsfehler haben. message_en.properties-Datei:

# Anwendungsdefinierte Fehlermeldungen
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-Fehlermeldungen, die verwendet werden sollen, wenn die Umwandlung von Formulardaten in Bean fehlschlägt
typeMismatch.int={0} Value must be an integer
typeMismatch.java.lang.Integer={0} must be an integer
typeMismatch={0} is of invalid format

# Anwendungsmeldungen für Annotationen, {ValidationClass}.{modelObjectName}.{field}
# das {0} ist Feldname, andere Felder sind in alphabetischer Reihenfolge, max und dann 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

# Generische Annotationsklassenmeldungen
Email=Email address is not valid
NotNull=This is a required field
NotEmpty=This is a required field
Past=Date should be Past

# Benutzerdefinierte Validierungsannotation
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.

Seiten anzeigen mit Formular und Fehlern

Da wir die Validierungsimplementierung des Spring-Frameworks verwenden, müssen wir Spring-Form-Tags verwenden, um die Fehler abzurufen und die Formulardaten und Variablennamen festzulegen. Unser custSave.jsp-Dateicode lautet wie folgt.

<%@ 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" wird verwendet, um den Namen des Modellattributs festzulegen, unter dem das Formularobjekt freigegeben wird. Sein Standardwert ist standardmäßig „command“, daher sollten wir ihn auf den Modellattributnamen setzen, den wir in unseren Controller-Klassen verwenden. springForm:errors wird verwendet, um Fehler zu rendern, falls vorhanden, die beim Rendern der Seite gefunden wurden. Das Attribut path wird verwendet, um die Objekteigenschaft festzulegen, die für die Datenbindung verwendet werden soll. Der Rest des Codes ist standardmäßiges HTML mit ein wenig CSS zur Formatierung von Fehlermeldungen. Unsere Datei custSaveSuccess.jsp sieht wie folgt aus.

<%@ 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>

Einfache JSP-Seite, die die Kundendaten anzeigt, wenn keine Validierungsfehler vorliegen, und diese Seite als Antwort zurückgegeben wird. Ihr Name lautet 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>

Datei 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>

Testen der Spring MVC Formularvalidierungsanwendung

Unsere Anwendung ist bereit zur Bereitstellung und Durchführung einiger Tests. Bereitstellen Sie sie in Ihrem bevorzugten Servlet-Container. Ich verwende Apache Tomcat 7, und unten sehen Sie einige Seiten mit Validierungsfehlermeldungen. Basierend auf Ihren Eingabedaten erhalten Sie möglicherweise auch unterschiedliche Fehlermeldungen. Das ist alles für die Validierung von Spring MVC-Formularen auf verschiedene Arten und die Verwendung von Ressourcenbündeln für lokalisierte Fehlermeldungen. Sie können das Beispieldprojekt über den untenstehenden Link herunterladen und damit herumspielen, um mehr zu erfahren.

Spring-Formularvalidierungsprojekt herunterladen

Source:
https://www.digitalocean.com/community/tutorials/spring-validation-example-mvc-validator