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


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow