La validation des données de classe (bean) en java n'est pas un nouveau sujet, mais il est également pertinent ici et je combinerai divers aspects: validation des données dans JSR-303, je montrerai comment le faire purement en Java et en utilisant Spring, comment le faire dans une application standard et sur le Web.
Contenu: Validation des données (JSR-303) dans
- application java standard
- en utilisant le printemps
- Association Java + Spring
- Spring mvc
Validation dans une application Java standard
Pour vérifier l'objet, des annotations sur les champs de la classe sont utilisées, c'est-à-dire modèle déclaratif. Les annotations sont déjà prêtes:
Null , @DecimalMin, @Digits, Pattern , Email , etc.
, et vous pouvez également créer le vôtre. Et donc il y a une classe (bean)
import javax.validation.constraints.Digits; import javax.validation.constraints.Size; public class Person { @Size(min=2, max=50) private String Name; @Digits(integer=3, fraction=0, message = " 3- ") @PersonAgeConstraint private Integer age; public Person(String name, Integer age) { Name = name; this.age = age; } }
Ici, dans l'exemple, les annotations prêtes de
taille et @ chiffres, et @PersonAgeConstraint propre. Comment faire votre propre:
- préparer l'annotation
@Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy=PersonAgeConstraintValidator.class) public @interface PersonAgeConstraint { String message() default "{value.negative}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
Dans message (), spécifiez la clé (value.negative) du fichier de ressources (ValidationMessages.properties) pour le message
value.negative = valeur négative
et implémentation de la classe de vérification - PersonAgeConstraintValidator.class
public class PersonAgeConstraintValidator implements ConstraintValidator<PersonAgeConstraint, Integer> { @Override public boolean isValid(Integer age, ConstraintValidatorContext constraintValidatorContext) { return age > 0; } }
Ma propre annotation est prête, nous l'ajoutons au champ et il est déjà possible de vérifier, tous les champs sur lesquels il y a des annotations seront vérifiés par les règles correspondantes.
import javax.validation.Validator; public class DemoJValidationApplicationTests {
Résultat dans la console
3-
Les messages pour les annotations standard peuvent être spécifiés dans le fichier de messages, en règle générale:
AnnotationName.entity.fieldname=
Structure du projet

fichier pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>DemoJSRvalidation</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>DemoJSRvalidation</name> <description>Demo project for Spring Boot JSR-303 validation</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Vérification progressive. Pour Class <?> [] Groups (), vous pouvez spécifier les types de classes par lesquels vous pouvez ensuite les regrouper, limiter la liste des vérifications, c.-à-d. utiliser comme filtre. Ainsi, la vérification peut se faire par étapes, 1) Par exemple, nous divisons l'examen d'une personne pour des raisons de santé, 2) puis les données professionnelles. Nous préparerons deux annotations
HealthConstraint et ProfessionalConstraint et leurs implémentations. Nous vérifions d'abord le respect de la santé, puis si cela passe par la santé, nous vérifions les données professionnelles.
Un exemple:
public class Person { @HealthConstraint(groups = Health.class) private Documents healthDocuments; @ProfessionalConstraint(groups = Professional.class) private Documents ProfessionalDocuments;
Exemple d'annotation HealthConstraint
@Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy=HealthConstraintValidator.class) public @interface HealthConstraint { String message() default "{health.documents}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
Exemple d'implémentation de HealthConstraintValidator
public class HealthConstraintValidator implements ConstraintValidator<HealthConstraint, Documents> { @Override public boolean isValid(Documents documents, ConstraintValidatorContext constraintValidatorContext) { return documents.contains(" 1"); } }
pour ProfessionalConstraint, tout est pareil
Vérifiez ensuite comme ceci:
@Test public void healthAndProfessionalValidators() { final Person person = new Person(" ", 45); person.setHealthDocuments(new Documents(Arrays.asList(" 1", " 3"))); person.setProfessionalDocuments(new Documents(Arrays.asList(" 1", " 4")));
Ces vérifications, par exemple, sont nécessaires lorsque nous chargeons des données à partir d'un fichier, d'un service Web et d'autres sources.
Documents de classe public class Documents { private List<String> tests = new ArrayList(); public Documents(List<String> tests) { this.tests.addAll(tests); } public boolean contains(String test) { return this.tests.contains(test); } }
Validation à l'aide de Spring
Spring a également sa propre interface Validator.
(org.springframework.validation.Validator)
comme en java
(javax.validation.Validator)
et c'est précisément sa mise en œuvre qui valide les données. Ce n'est plus une approche déclarative, mais elle a sa propre flexibilité et extensibilité. Pour le même bac, je ferai la même vérification d'âge.
En remplaçant les deux méthodes, nous validons
@Service public class PersonValidator implements Validator { @Override public boolean supports(Class<?> aClass) { return Person.class.equals(aClass); } @Override public void validate(Object obj, Errors errors) { Person p = (Person) obj; if (p.getAge() < 0) { errors.rejectValue("age", "value.negative"); } } }
value.negative - est également la clé du fichier de messages,
public boolean supports
déterminent le type de classe pris en charge.
La vérification est lancée via DataBinder
Un exemple:
@RunWith(SpringRunner.class) @SpringBootTest public class DemoJValidationApplicationTests {
Toutes les vérifications qui ont implémenté org.springframework.validation.Validator pour la classe Person seront effectuées.
Vous pouvez également ajouter plusieurs validateurs, dataBinder.addValidators, vous pouvez faire une composition de règles (un appel d'une règle, une autre), par exemple:
public class OtherValidator implements Validator { @Override public boolean supports(Class<?> aClass) { return Person.class.equals(aClass); } @Override public void validate(Object obj, Errors errors) {
Pour une raison quelconque, je m'attendais à ce que Spring effectue également les vérifications indiquées dans les annotations, mais non, cet appel doit être effectué indépendamment.
Structure du projet

fichier pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>DemoJSRvalidation</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>DemoJSRvalidation</name> <description>Demo project for Spring Boot JSR-303 validation</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Java & Spring
Évidemment, je veux utiliser deux approches dans la vérification des données - Java et Spring, vous pouvez les combiner, à savoir ajouter l'appel javax.validation.Validator au
validateur Spring.
Exemple
import javax.validation.Validator; @Service public class PersonValidator implements org.springframework.validation.Validator {
En utilisant le ressort, nous faisons l'injection
javax.validation.Validator
@Autowired
private Validator validator;
plus loin sur la méthode
public void validate(Object obj, Errors errors)
effectuer des vérifications déclaratives sur java, puis effectuer toutes les vérifications de la classe Person sur spring org.springframework.validation.Validator.
Nous effectuons également une vérification au printemps
@Test public void testValidators() { final Person person = new Person("", -4500); final DataBinder dataBinder = new DataBinder(person); dataBinder.addValidators(personValidator); dataBinder.validate(); if (dataBinder.getBindingResult().hasErrors()) { dataBinder.getBindingResult().getAllErrors()
Maintenant, dans la collection, il y aura des vérifications par rapport aux annotations Java et Spring (org.springframework.validation.Validator) pour Person
Sortie console
()
3- ()
(spring)
Structure du projet

Spring mvc
Bien sûr, maintenant tout cela peut être appliqué dans une application Web.
Nous ajoutons le contrôleur, la page jsp au projet (ici, en passant, il peut y avoir d'autres options, par exemple, générer des pages en utilisant freeMarker, etc.), le style css, la dépendance pom. Et donc pour
1) Contrôleur MVC
import org.springframework.validation.Validator; @Controller public class DemoJValidationController { @Autowired @Qualifier("personValidator")
Ici avec PersonValidator connecté par injection de ressort
@Autowired
@Qualifier("personValidator") // spring validator
private Validator personValidator;
définissez PersonValidator sur initBinder
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(personValidator);
}
Validation déclenchée par l'annotation
@Valid
Dans ce cas, seule la vérification du ressort sera effectuée, les vérifications déclaratives seront ignorées.
En cas de suppression du code
@InitBinder
protected void initBinder(WebDataBinder binder)
au contraire, tous les contrôles déclaratifs seront effectués et le ressort sera ignoré.
Pour effectuer tous les contrôles, déclaratifs et printaniers, vous pouvez procéder comme suit:
Supprimer @InitBinder, laisser l'injection
@Autowired
@Qualifier("personValidator") // spring validator
private Validator personValidator;
et ajouter manuellement un appel de vérification du printemps
// spring validate
personValidator.validate(person, bindingResult);
Voici le code:
@Controller public class DemoJValidationController { @Autowired @Qualifier("personValidator")
c'est-à-dire des vérifications supplémentaires du printemps seront ajoutées à bindingResult :-), c'est ce que je voulais!
La liaison de données dans jsp et le modèle est effectuée par l'attribut -
modelAttribute="person"
Dans l'exemple, la bibliothèque de balises de formulaire de SpringMVC est connectée.
Les ressources restantes de cet exemple sont:
DemoJValidationApplication @SpringBootApplication @ImportResource("classpath:configuration.xml") public class DemoJValidationApplication { public static void main(String[] args) { SpringApplication.run(DemoJValidationApplication.class, args); } }
Configuration du ressort
configuration.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/c" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename" value="classpath:message"/> <property name="defaultEncoding" value="UTF-8"/> </bean> <mvc:annotation-driven/> <mvc:resources mapping="/resources/**" location="classpath:/META-INF/resources/"/> </beans>
personEdit.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <link href="<c:url value="/resources/my.css" />" rel="stylesheet"> <title>Person</title> </head> <body> <h3> Enter Person. </h3> <form:form method="POST" modelAttribute="person" action="save"> <div> Name: <form:input path="name"/> <form:errors path="name" cssClass="error"/> </div> <div> Age: <form:input path="age"/> <form:errors path="age" cssClass="error"/> </div> <button type="submit">Registration</button> </form:form> </body> </html>
saveSuccess.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <link href="<c:url value="/resources/my.css" />" rel="stylesheet"> <title>Person Saved Successfully</title> </head> <body> <h3> Person Saved Successfully. </h3> <form:form method="POST" modelAttribute="person" action="edit"> <div> ${name} </div> <div> ${age} </div> <button type="submit">Edit</button> </form:form> </body> </html>
my.css span.error { color: red; } form div{ margin: 5px; }
fichier pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>DemoJSRvalidation</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>DemoJSRvalidation</name> <description>Demo project for Spring Boot JSR-303 validation</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.1.0.Final</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Structure du projet

Travail d'application

Matériaux
Spécification de validation du bean