spring
Spring JSR 303 Bean Validierung
Suche…
Einführung
Spring bietet Unterstützung für die JSR303-Bean-Validierung. Wir können dies für die Validierung der Input-Bean verwenden. Trennen Sie die Validierungslogik von der Geschäftslogik mit JSR303.
JSR303 Annotationsbasierte Validierungen in Springs-Beispielen
Fügen Sie Ihrem Klassenpfad eine beliebige JSR 303-Implementierung hinzu. Der häufig verwendete ist der Hibernate-Validator von Hibernate.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
Nehmen wir an, es gibt eine Rest-API, um Benutzer im System anzulegen
@RequestMapping(value="/registeruser", method=RequestMethod.POST)
public String registerUser(User user);
Das Eingabe-Json-Beispiel würde wie folgt aussehen
{"username" : "[email protected]", "password" : "password1", "password2":"password1"}
User.java
public class User {
private String username;
private String password;
private String password2;
getXXX and setXXX
}
Wir können JSR 303-Validierungen für die Benutzerklasse wie folgt definieren.
public class User {
@NotEmpty
@Size(min=5)
@Email
private String username;
@NotEmpty
private String password;
@NotEmpty
private String password2;
}
Möglicherweise müssen wir auch einen Business-Validator wie Kennwort und Passwort2 (Kennwort bestätigen) verwenden. Hierfür können wir einen benutzerdefinierten Validator hinzufügen (siehe unten). Schreiben Sie eine benutzerdefinierte Anmerkung zum Kommentieren des Datenfelds.
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PasswordValidator.class)
public @interface GoodPassword {
String message() default "Passwords wont match.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Schreiben Sie eine Validator-Klasse, um die Validierungslogik anzuwenden.
public class PastValidator implements ConstraintValidator<GoodPassword, User> {
@Override
public void initialize(GoodPassword annotation) {}
@Override
public boolean isValid(User user, ConstraintValidatorContext context) {
return user.getPassword().equals(user.getPassword2());
}
}
Hinzufügen dieser Validierung zur Benutzerklasse
@GoodPassword
public class User {
@NotEmpty
@Size(min=5)
@Email
private String username;
@NotEmpty
private String password;
@NotEmpty
private String password2;
}
@Valid löst die Validierung in Spring aus. BindingResult ist ein von spring injiziertes Objekt, das nach der Validierung eine Fehlerliste enthält.
public String registerUser(@Valid User user, BindingResult result);
Die Annotation JSR 303 enthält Nachrichtenattribute, die zum Bereitstellen benutzerdefinierter Nachrichten verwendet werden können.
@GoodPassword
public class User {
@NotEmpty(message="Username Cant be empty")
@Size(min=5, message="Username cant be les than 5 chars")
@Email(message="Should be in email format")
private String username;
@NotEmpty(message="Password cant be empty")
private String password;
@NotEmpty(message="Password2 cant be empty")
private String password2;
}
Spring JSR 303 Validation - Anpassen von Fehlermeldungen
Angenommen, wir haben eine einfache Klasse mit Validierungsanmerkungen
public class UserDTO {
@NotEmpty
private String name;
@Min(18)
private int age;
//getters/setters
}
Ein Controller zur Überprüfung der UserDTO-Gültigkeit.
@RestController
public class ValidationController {
@RequestMapping(value = "/validate", method = RequestMethod.POST)
public ResponseEntity<String> check(@Valid @RequestBody UserDTO userDTO,
BindingResult bindingResult) {
return new ResponseEntity<>("ok" , HttpStatus.OK);
}
}
Und ein Test.
@Test
public void testValid() throws Exception {
TestRestTemplate template = new TestRestTemplate();
String url = base + contextPath + "/validate";
Map<String, Object> params = new HashMap<>();
params.put("name", "");
params.put("age", "10");
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("Content-Type", "application/json");
HttpEntity<Map<String, Object>> request = new HttpEntity<>(params, headers);
String res = template.postForObject(url, request, String.class);
assertThat(res, equalTo("ok"));
}
Sowohl Name als auch Alter sind ungültig. In BindingResult gibt es zwei Validierungsfehler. Jeder hat eine Reihe von Codes.
Codes für Min-Check
0 = "Min.userDTO.age"
1 = "Min.age"
2 = "Min.int"
3 = "Min"
Und für NotEmpty prüfen
0 = "NotEmpty.userDTO.name"
1 = "NotEmpty.name"
2 = "NotEmpty.java.lang.String"
3 = "NotEmpty"
Fügen wir eine custom.properties-Datei hinzu, um Standardnachrichten zu ersetzen.
@SpringBootApplication
@Configuration
public class DemoApplication {
@Bean(name = "messageSource")
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource();
bean.setBasename("classpath:custom");
bean.setDefaultEncoding("UTF-8");
return bean;
}
@Bean(name = "validator")
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Wenn wir der Datei custom.properties die Zeile hinzufügen
NotEmpty=The field must not be empty!
Der neue Wert wird für den Fehler angezeigt. Um den Nachrichtenvalidator aufzulösen, durchsucht er die Codes von Anfang an, um die richtigen Nachrichten zu finden.
Wenn wir in der .properties-Datei den NotEmpty
Schlüssel für alle Fälle definieren, in denen die Annotation @NotEmpty
wird, wird unsere Nachricht angewendet.
Wenn wir eine Nachricht definieren
Min.int=Some custom message here.
Alle Anmerkungen, bei denen wir min-to-integer-Werte überprüfen, verwenden die neu definierte Nachricht.
Die gleiche Logik kann angewendet werden, wenn die Überprüfungsfehlermeldungen lokalisiert werden müssen.
@Validierung zum Validieren von verschachtelten POJOs
Angenommen, wir haben einen POJO-Klassenbenutzer, den wir validieren müssen.
public class User {
@NotEmpty
@Size(min=5)
@Email
private String email;
}
und eine Controller-Methode zum Validieren der Benutzerinstanz
public String registerUser(@Valid User user, BindingResult result);
Lassen Sie uns den Benutzer mit einer verschachtelten POJO-Adresse erweitern, die wir ebenfalls überprüfen müssen.
public class Address {
@NotEmpty
@Size(min=2, max=3)
private String countryCode;
}
@Valid
einfach @Valid
Annotation im Adressfeld hinzu, um die Überprüfung verschachtelter POJOs @Valid
.
public class User {
@NotEmpty
@Size(min=5)
@Email
private String email;
@Valid
private Address address;
}