Spring Validation Overview
During development, we often encounter the need for parameter verification. For example, when a user registers, it is necessary to verify that the user name cannot be empty, the length of the user name does not exceed 20 characters, the mobile phone number is in a legal mobile phone number format, etc. If we use the ordinary method, we will couple the verification code with the real business processing logic, and if we want to add a new verification logic in the future, we will need to modify multiple places. Spring validation allows object verification rules to be defined through annotations, which separates verification from business logic, making code writing more convenient. Spring Validation is actually a further encapsulation of Hibernate Validator to facilitate use in Spring.
There are many verification methods in Spring
The first is to implement the org.springframework.validation.Validator interface and then call this class in the codeThe second is to perform verification according to the Bean Validation method, that is, through annotations
The third method is implementation verification based on method
The fourth way to implement custom verification
Implemented by implementing the Validator interface
Create submodule spring6-validator
Introduce dependencies
<dependencies> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>7.0.5.Final</version> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>jakarta.el</artifactId> <version>4.0.1</version> </dependency> </dependencies>
Create entity classes, define attributes, and create corresponding set and get methods
public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Create classes, implement interfaces, implement interface methods, and write verification logic
The supports method is used to indicate which type this check is used on
validate is the place to set the verification logic. ValidatorUtils is a verification tool class encapsulated by Spring to help quickly implement verification.
public class PersonValidator implements Validator { @Override public boolean supports(Class<?> clazz) { //supports method is used to indicate which type this check is used on return Person.class.equals(clazz); } //Verification rules @Override public void validate(Object target, Errors errors) { //validate is the place to set the verification logic. ValidatorUtils is a verification tool class encapsulated by Spring to help quickly implement verification. //name cannot be empty ValidationUtils.rejectIfEmpty(errors,"name","name.empty","name is null"); //age cannot be less than 0 or greater than 100 Person p = (Person) target; if (p.getAge() < 0){ errors.rejectValue("age","age.value.error","age < 0"); } else if (p.getAge() > 200) { errors.rejectValue("age","age.value.old","age > 200"); } } }
Complete test
//Verification test public class TestPerson { public static void main(String[] args) { //Create person object Person person = new Person(); //Create person corresponding databinder DataBinder binder = new DataBinder(person); //Set the validator binder.setValidator(new PersonValidator()); //Call method to perform verification binder.validate(); //Output verification results BindingResult result = binder.getBindingResult(); System.out.println(result.getAllErrors()); } }
Bean Validation annotation implementation
Using the Bean Validation verification method is how to inject the javax.validation.ValidatorFactory and javax.validation.Validator required for Bean Validation into the container.
Spring has an implementation class by default, LocalValidatorFactoryBean, which implements the interface in Bean Validation above, and also implements the org.springframework.validation.Validator interface.
Create the configuration class ValidationConfig and configure LocalValidatorFactoryBean
@Configuration @ComponentScan("com.yogurt.spring6.validator.two") public class ValidationConfig { @Bean public LocalValidatorFactoryBean validator(){ return new LocalValidatorFactoryBean(); } }
Create an entity class, define attributes, create corresponding set and get methods, and use annotations to set verification rules on the attributes
Commonly used annotations
@NotNull The limit must not be null
@NotEmpty only works on string types, the string is not empty, and the length is not 0@NotBlank only works on string types, the string is not empty, and the string after trim0 is not an empty string @DecimalMax(value) The limit must be a number not greater than the specified value
@DecimalMin(value) The limit must be a number not less than the specified value
@Max(value) The limit must be a number not greater than the specified value
@Min(value) The limit must be a number that is not less than the specified value. The limit must conform to the specified regular expression @Pattern(value)
@size(max,min) limits the character length to between min and max
@Email verifies that the element value of the annotation is Email. You can also specify a custom email format through regular expressions and flags.
public class User { @NotNull private String name; @Min(0) @Max(150) private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Use annotations to set validation rules on attributes
Create validator
Use native: import jakarta.validation.Validator;
@Service public class MyValidation1 { @Autowired private Validator validator; private boolean validatorByUserOne(User user){ Set<ConstraintViolation<User>> validate = validator.validate(user); return validate.isEmpty(); } }
Use spring framework: import org.springframework.validation.Validator;
@Service public class MyValidation2 { @Autowired private Validator validator; public boolean validatorByUserTwo(User user){ BindException bindException = new BindException(user, user.getName()); validator.validate(user,bindException); return bindException.hasErrors(); } }
Complete test
Native test:
@Test public void testValidationOne(){ ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class); MyValidation1 validation1 = context.getBean(MyValidation1.class); User user = new User(); //user.setName("luck"); //user.setAge(20); boolean message = validation1.validatorByUserOne(user); System.out.println(message); }
normal result
spring framework test:
@Test public void testValidationTwo(){ ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class); MyValidation2 validation2 = context.getBean(MyValidation2.class); User user = new User(); // user.setName("luck"); // user.setAge(20); boolean message = validation2.validatorByUserTwo(user); System.out.println(message); } }
Error reported:
java.lang.IllegalArgumentException: Object name must not be null
Modify–>Set name and age:
@Test public void testValidationTwo(){ ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class); MyValidation2 validation2 = context.getBean(MyValidation2.class); User user = new User(); user.setName("luck"); user.setAge(20); boolean message = validation2.validatorByUserTwo(user); System.out.println(message); } }
Method-based verification
Create configuration class ValidationConfig
@Configuration @ComponentScan("com.yogurt.spring6.validator.three") public class ValidationConfig { @Bean public MethodValidationPostProcessor validationPostProcessor(){ return new MethodValidationPostProcessor(); } }
Create an entity class, define attributes, create corresponding set and get methods, and use annotations to set verification rules on the attributes
public class User { @NotNull private String name; @Min(0) @Max(150) private int age; @Pattern(regexp = "^1(3|4|5|7|8)\d{9}$",message = "Mobile phone number format is wrong") @NotBlank(message = "Mobile phone number cannot be blank") private String phone; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
Use annotations to set validation rules on attributes
Create validator
@Service @Validated public class MyService { public String testMethod(@NotNull @Valid User user){ return user.toString(); } }
Complete test
public class TestUser { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class); MyService service = context.getBean(MyService.class); User user = new User(); //user.setName("lucy"); //user.setPhone("15545451223"); service.testMethod(user); } }
Error report: Exception in thread “main” jakarta.validation.ConstraintViolationException: testMethod.arg0.name: cannot be null, testMethod.arg0.phone: mobile phone number cannot be empty
Modify–>Set name and mobile phone number:
public class TestUser { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class); MyService service = context.getBean(MyService.class); User user = new User(); user.setName("lucy"); user.setPhone("15545451223"); service.testMethod(user); } }