Das Validieren von Klassendaten (Bean) in Java ist kein neues Thema, aber es ist auch hier relevant und ich werde verschiedene Aspekte kombinieren: Datenvalidierung in JSR-303, ich werde zeigen, wie dies rein in Java und mit Spring gemacht wird, wie es in einer Standardanwendung und im Web gemacht wird.
Inhalt: Datenvalidierung (JSR-303) in
- Standard Java-Anwendung
- mit Spring
- Java + Spring Association
- Frühling mvc
Validierung in einer Standard-Java-Anwendung
Um das Objekt zu überprüfen, werden Anmerkungen zu den Feldern der Klasse verwendet, d.h. deklaratives Modell. Anmerkungen sind bereits fertig:
Null , @DecimalMin, @Digits, Pattern , Email usw.
, und Sie können auch Ihre eigenen machen. Und so gibt es eine Klasse (Bohne)
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; } }
Hier im Beispiel sind
Size und @Digits fertige Annotationen und @PersonAgeConstraint eigene. So machen Sie Ihre eigenen:
- Bereiten Sie die Anmerkung vor
@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 {}; }
Geben Sie in message () den Schlüssel (value.negative) aus der Ressourcendatei (ValidationMessages.properties) für die Nachricht an
value.negative = Negativer Wert
und Implementierung der Verifizierungsklasse - PersonAgeConstraintValidator.class
public class PersonAgeConstraintValidator implements ConstraintValidator<PersonAgeConstraint, Integer> { @Override public boolean isValid(Integer age, ConstraintValidatorContext constraintValidatorContext) { return age > 0; } }
Meine eigene Anmerkung ist fertig, wir fügen sie dem Feld hinzu und Sie können bereits überprüfen, ob alle Felder, in denen Anmerkungen vorhanden sind, durch die entsprechenden Regeln überprüft werden.
import javax.validation.Validator; public class DemoJValidationApplicationTests {
Ergebnis in der Konsole
3-
Nachrichten für Standardanmerkungen können in der Regel in der Nachrichtendatei angegeben werden:
AnnotationName.entity.fieldname=
Projektstruktur

POM-Datei <?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>
Stufenweise Überprüfung. Für Class <?> [] Groups () können Sie die Klassentypen angeben, nach denen Sie sie dann gruppieren können, und die Liste der Prüfungen einschränken, d. H. als Filter verwenden. So kann die Überprüfung schrittweise erfolgen: 1) Zum Beispiel teilen wir die Untersuchung einer Person aus gesundheitlichen Gründen auf, 2) und dann professionelle Daten. Wir werden zwei Anmerkungen vorbereiten
HealthConstraint und ProfessionalConstraint und Implementierungen für sie. Zuerst überprüfen wir die Einhaltung der Gesundheit und dann, wenn es durch die Gesundheit geht, überprüfen wir professionelle Daten.
Ein Beispiel:
public class Person { @HealthConstraint(groups = Health.class) private Documents healthDocuments; @ProfessionalConstraint(groups = Professional.class) private Documents ProfessionalDocuments;
Beispiel für eine HealthConstraint-Annotation
@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 {}; }
Implementierungsbeispiel für HealthConstraintValidator
public class HealthConstraintValidator implements ConstraintValidator<HealthConstraint, Documents> { @Override public boolean isValid(Documents documents, ConstraintValidatorContext constraintValidatorContext) { return documents.contains(" 1"); } }
Für ProfessionalConstraint ist alles gleich
Nächste Prüfung wie folgt:
@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")));
Solche Überprüfungen sind beispielsweise erforderlich, wenn wir Daten aus einer Datei, einem Webdienst und anderen Quellen laden.
Klassendokumente 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); } }
Validierung mit Spring
Spring hat auch eine eigene Validator-Oberfläche.
(org.springframework.validation.Validator)
wie in Java
(javax.validation.Validator)
und genau seine Implementierung validiert die Daten. Dies ist kein deklarativer Ansatz mehr, sondern hat seine eigene Flexibilität und Erweiterbarkeit. Für den gleichen Behälter mache ich die gleiche Altersüberprüfung.
Durch Überschreiben der beiden Methoden validieren wir
@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 - ist auch der Schlüssel in der Nachrichtendatei.
public boolean supports
bestimmt den Typ der unterstützten Klasse.
Die Überprüfung wird über den DataBinder gestartet
Ein Beispiel:
@RunWith(SpringRunner.class) @SpringBootTest public class DemoJValidationApplicationTests {
Alle Überprüfungen, die org.springframework.validation.Validator für die Person-Klasse implementiert haben, werden durchgeführt.
Sie können auch mehrere Validatoren hinzufügen, dataBinder.addValidators. Sie können eine Zusammenstellung von Regeln erstellen (ein Aufruf von einer Regel, einer anderen), zum Beispiel:
public class OtherValidator implements Validator { @Override public boolean supports(Class<?> aClass) { return Person.class.equals(aClass); } @Override public void validate(Object obj, Errors errors) {
Aus irgendeinem Grund habe ich erwartet, dass Spring auch die in den Anmerkungen angegebenen Überprüfungen durchführt, aber nein, dieser Aufruf muss unabhängig erfolgen.
Projektstruktur

POM-Datei <?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 & Frühling
Natürlich möchte ich bei der Datenüberprüfung zwei Ansätze verwenden - Java und Spring. Sie können sie kombinieren, nämlich den Aufruf javax.validation.Validator zu Spring validator hinzufügen.
Beispiel
import javax.validation.Validator; @Service public class PersonValidator implements org.springframework.validation.Validator {
Mit der Feder
javax.validation.Validator
wir
javax.validation.Validator
@Autowired
private Validator validator;
weiter auf der Methode
public void validate(Object obj, Errors errors)
Führen Sie deklarative Überprüfungen für Java durch und führen Sie dann alle Überprüfungen für die Person-Klasse für spring org.springframework.validation.Validator durch.
Wir führen die Überprüfung auch bis zum Frühjahr durch
@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()
Jetzt in der Sammlung gibt es Überprüfungen gegen Java- und Spring-Annotationen (org.springframework.validation.Validator) für Person
Konsolenausgabe
()
3- ()
(spring)
Projektstruktur

Frühling mvc
Natürlich kann dies alles jetzt in einer Webanwendung angewendet werden.
Wir fügen dem Projekt den Controller, die JSP-Seite hinzu (hier gibt es übrigens möglicherweise andere Optionen, z. B. das Generieren von Seiten mit freeMarker usw.), den CSS-Stil und die POM-Abhängigkeit. Und so in Ordnung
1) MVC-Controller
import org.springframework.validation.Validator; @Controller public class DemoJValidationController { @Autowired @Qualifier("personValidator")
Hier mit Federeinspritzung PersonValidator angeschlossen
@Autowired
@Qualifier("personValidator") // spring validator
private Validator personValidator;
Setzen Sie PersonValidator auf initBinder
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(personValidator);
}
Validierung ausgelöst durch
@Valid
Annotation
In diesem Fall wird nur die Federprüfung durchgeführt, deklarative Prüfungen werden ignoriert.
Wenn aus dem Code entfernt
@InitBinder
protected void initBinder(WebDataBinder binder)
Im Gegenteil, alle deklarativen Prüfungen werden durchgeführt und die Feder wird ignoriert.
Um alle deklarativen und Frühjahrsprüfungen abzuschließen, können Sie Folgendes tun:
@InitBinder entfernen, Injektion lassen
@Autowired
@Qualifier("personValidator") // spring validator
private Validator personValidator;
und fügen Sie manuell einen Federprüfungsaufruf hinzu
// spring validate
personValidator.validate(person, bindingResult);
Hier ist der Code:
@Controller public class DemoJValidationController { @Autowired @Qualifier("personValidator")
d.h. zusätzliche Schecks vom Frühling werden zu bindingResult hinzugefügt :-), was ich wollte!
Die
modelAttribute="person"
in jsp und model erfolgt über das Attribut -
modelAttribute="person"
Im Beispiel ist die Form-Tag-Bibliothek von SpringMVC verbunden.
Die verbleibenden Ressourcen dieses Beispiels sind:
DemoJValidationApplication @SpringBootApplication @ImportResource("classpath:configuration.xml") public class DemoJValidationApplication { public static void main(String[] args) { SpringApplication.run(DemoJValidationApplication.class, args); } }
Federkonfiguration
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; }
POM-Datei <?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>
Projektstruktur

Bewerbungsarbeit

Material
Bean-Validierungsspezifikation