Szukaj…


Wprowadzenie

Wiosna ma obsługę sprawdzania poprawności komponentu JSR303. Możemy to wykorzystać do sprawdzenia poprawności komponentu bean. Oddziel logikę sprawdzania poprawności od logiki biznesowej za pomocą JSR303.

JSR303 Sprawdzanie poprawności oparte na adnotacjach w przykładach Springs

Dodaj dowolną implementację JSR 303 do ścieżki klasy. Popularnym jest walidator Hibernacja od Hibernacji.

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.2.0.Final</version>
</dependency>

Powiedzmy, że istnieje interfejs API umożliwiający utworzenie użytkownika w systemie

@RequestMapping(value="/registeruser", method=RequestMethod.POST)
public String registerUser(User user);

Próbka wejściowa json wyglądałaby jak poniżej

{"username" : "[email protected]", "password" : "password1", "password2":"password1"}

User.java

public class User {

    private String username;
    private String password;
    private String password2;

    getXXX and setXXX

}

Możemy zdefiniować walidacje JSR 303 w klasie użytkownika, jak poniżej.

public class User {

    @NotEmpty
    @Size(min=5)
    @Email
    private String username;
    
    @NotEmpty
    private String password;
    
    @NotEmpty
    private String password2;

}

Może być też konieczne, aby walidator biznesowy, taki jak hasło i hasło2 (potwierdź hasło) są takie same, w tym celu możemy dodać niestandardowy walidator, jak poniżej. Napisz niestandardową adnotację do opisu pola danych.

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

Napisz klasę walidatora do stosowania logiki walidacji.

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

Dodanie tej weryfikacji do klasy użytkownika

@GoodPassword
public class User {

    @NotEmpty
    @Size(min=5)
    @Email
    private String username;
    
    @NotEmpty
    private String password;
    
    @NotEmpty
    private String password2;
}

@ Ważny uruchamia sprawdzanie poprawności wiosną. BindingResult to obiekt wstrzykiwany przez sprężynę, który ma listę błędów po sprawdzeniu poprawności.

public String registerUser(@Valid User user, BindingResult result);

Adnotacja JSR 303 zawiera atrybuty wiadomości, których można używać do dostarczania wiadomości niestandardowych.

@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 - Dostosuj komunikaty o błędach

Załóżmy, że mamy prostą klasę z adnotacjami sprawdzania poprawności

public class UserDTO {
    @NotEmpty
    private String name;

    @Min(18)
    private int age;

//getters/setters
}

Kontroler do sprawdzania ważności UserDTO.

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

I 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"));
}

Zarówno imię, jak i wiek są nieprawidłowe, więc w BindingResult mamy dwa błędy sprawdzania poprawności. Każdy ma szereg kodów.

Kody kontroli min

0 = "Min.userDTO.age"
1 = "Min.age"
2 = "Min.int"
3 = "Min"

I dla czeku NotEmpty

0 = "NotEmpty.userDTO.name"
1 = "NotEmpty.name"
2 = "NotEmpty.java.lang.String"
3 = "NotEmpty"

Dodajmy plik custom.properties, aby zastąpić komunikaty domyślne.

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

Jeśli dodamy do pliku custom.properties linię

NotEmpty=The field must not be empty!

Nowa wartość jest wyświetlana dla błędu. Aby rozwiązać problem, sprawdzacz poprawności przegląda kody od początku, aby znaleźć odpowiednie komunikaty.

Tak więc, gdy definiujemy NotEmpty klucz w pliku .properties wszystkich przypadkach, w których @NotEmpty służy adnotacja stosowana jest nasze przesłanie.

Jeśli zdefiniujemy wiadomość

Min.int=Some custom message here.

Wszystkie adnotacje, w których sprawdzamy min. Wartości całkowite, używają nowo zdefiniowanej wiadomości.

Tę samą logikę można zastosować, jeśli musimy zlokalizować komunikaty o błędach sprawdzania poprawności.

@ Prawidłowe użycie do sprawdzania zagnieżdżonych POJO

Załóżmy, że mamy użytkownika klasy POJO, który musimy zweryfikować.

public class User {

    @NotEmpty
    @Size(min=5)
    @Email
    private String email;
}

oraz metoda kontrolera do sprawdzania poprawności instancji użytkownika

public String registerUser(@Valid User user, BindingResult result);

Rozszerzmy użytkownika o zagnieżdżony adres POJO, który również musimy zweryfikować.

public class Address {

    @NotEmpty
    @Size(min=2, max=3)
    private String countryCode;
}

Wystarczy dodać adnotację @Valid w polu adresu, aby uruchomić sprawdzanie poprawności zagnieżdżonych POJO.

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow