spring
Весна JSR 303 Проверка валика
Поиск…
Вступление
Spring имеет поддержку проверки бонуса JSR303. Мы можем использовать это для проверки входных бинов. Отдельная логика проверки из бизнес-логики с использованием JSR303.
JSR303 Подтверждения, основанные на аннотациях, в примерах Springs
Добавьте любую реализацию JSR 303 в свой путь к классам. Популярным из них является Hibernate validator из Hibernate.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
Допустим, что существует rest api для создания пользователя в системе
@RequestMapping(value="/registeruser", method=RequestMethod.POST)
public String registerUser(User user);
Образец ввода json будет выглядеть следующим образом:
{"username" : "[email protected]", "password" : "password1", "password2":"password1"}
User.java
public class User {
private String username;
private String password;
private String password2;
getXXX and setXXX
}
Мы можем определить валидации JSR 303 в пользовательском классе, как показано ниже.
public class User {
@NotEmpty
@Size(min=5)
@Email
private String username;
@NotEmpty
private String password;
@NotEmpty
private String password2;
}
Нам также может понадобиться иметь валидатор для бизнеса, например пароль и пароль2 (подтвердить пароль), то же самое, для этого мы можем добавить специальный валидатор, как показано ниже. Напишите пользовательскую аннотацию для аннотирования поля данных.
@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 {};
}
Напишите класс Validator для применения логики проверки.
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());
}
}
Добавление этой проверки в пользовательский класс
@GoodPassword
public class User {
@NotEmpty
@Size(min=5)
@Email
private String username;
@NotEmpty
private String password;
@NotEmpty
private String password2;
}
@Valid запускает проверку весной. BindingResult - это объект, введенный весной, у которого есть список ошибок после проверки.
public String registerUser(@Valid User user, BindingResult result);
В аннотации JSR 303 есть атрибуты сообщений, которые могут использоваться для предоставления пользовательских сообщений.
@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 - настройка сообщений об ошибках
Предположим, что у нас есть простой класс с аннотациями проверки
public class UserDTO {
@NotEmpty
private String name;
@Min(18)
private int age;
//getters/setters
}
Контроллер для проверки достоверности 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);
}
}
И тест.
@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"));
}
И имя, и возраст недействительны, поэтому в BindingResult мы имеем две ошибки проверки. Каждый из них имеет массив кодов.
Коды для проверки Мин
0 = "Min.userDTO.age"
1 = "Min.age"
2 = "Min.int"
3 = "Min"
И для проверки NotEmpty
0 = "NotEmpty.userDTO.name"
1 = "NotEmpty.name"
2 = "NotEmpty.java.lang.String"
3 = "NotEmpty"
Давайте добавим файл custom.properties, чтобы заменить сообщения по умолчанию.
@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);
}
}
Если мы добавим в файл custom.properties строку
NotEmpty=The field must not be empty!
Новое значение отображается для ошибки. Чтобы разрешить проверку сообщений, просматривайте коды, начиная с начала, чтобы найти правильные сообщения.
Таким образом, когда мы определяем ключ NotEmpty
в файле .properties для всех случаев, когда @NotEmpty
аннотация @NotEmpty
наше сообщение применяется.
Если мы определим сообщение
Min.int=Some custom message here.
Все аннотации, в которых мы проверяем приложение min на целые значения, используют новое заданное сообщение.
Та же логика может быть применена, если нам нужно локализовать сообщения об ошибках проверки.
Использование @Valid для проверки вложенных POJO
Предположим, у нас есть пользователь POJO, который нам нужно проверить.
public class User {
@NotEmpty
@Size(min=5)
@Email
private String email;
}
и метод контроллера для проверки экземпляра пользователя
public String registerUser(@Valid User user, BindingResult result);
Расширим Пользователь с вложенным POJO-адресом, который нам также нужно проверить.
public class Address {
@NotEmpty
@Size(min=2, max=3)
private String countryCode;
}
Просто добавьте аннотацию @Valid
в поле адреса, чтобы запустить проверку вложенных POJO.
public class User {
@NotEmpty
@Size(min=5)
@Email
private String email;
@Valid
private Address address;
}