Table of contents
2. Implementation of JSR 303 and Hibernate
Data verification Validation
1. Introduction to data verification
Data verification is divided into client data verification and server data verification. All to ensure data integrity. The client data verification can be directly verified by the client script. For example, in a B/S model project, you can choose to use JavaScript or jQuery for client-side data validation. In Jingdong Mall, if neither the user name nor the password is entered, if you click Login directly, you will be prompted to enter the account name and password, which is the client verification.
A project that only has client-side data verification is not rigorous. In order to prevent illegal personnel from directly accessing the server through URL or HTTP tools and sending illegal data, the server should also have data verification for insurance purposes. This kind of client and service When both ends have data verification, it is called double verification .
Data validation of the Spring framework can be used on the server side. Both web and non-web environments can be used. Data validation in the Spring framework is mainly used in the web layer, but can also be applied in other layers. It needs to be implemented with the help of the Validator interface and DataBinder.
2. Spring framework Validator interface use
Before the code, let's introduce the Validator interface
public interface Validator {
/**
* 判断校验的类,如果支持对这个类的校验返回true,否则返回false
* @return 是否支持当前类类型
*/
boolean supports(Class<?> clazz);
/**
* 校验的具体逻辑
* @param target 目标对象
* @param errors 校验不同过后的错误信息。可以通过ValidationUtils快速校验和设置错误信息
*/
void validate(Object target, Errors errors);
}
ValidationUtils is a tool class that can quickly determine whether an attribute is null, the length is 0, the acquisition is all spaces, and the error is bound.
2.1 Prepare an entity class
Or use the People class for testing. There are two attributes given in it.
package com.tong.validation;
import lombok.Data;
@Data
public class People {
private String name;
private int age;
}
2.2 New verification class
Create a new com.tong.validation.MyValidator. Both the class name and the package where the class is located are defined arbitrarily, and there is no mandatory requirement.
public class MyValidator implements Validator {
// 定义需要对哪个类进行校验
@Override
public boolean supports(Class<?> clazz) {
if(clazz.equals(People.class)){
return true;
}
return false;
}
// 具体校验规则
// 简单判断是否为空可以使用工具类。其他的校验规则需要自己定义
@Override
public void validate(Object target, Errors errors) {
// rejectIfEmpty(Errors对象,“校验的属性”,"错误码,可以设置为null",“校验不通过时日志打印的消息”):为空校验不通过
ValidationUtils.rejectIfEmpty(errors,"name",null,"姓名不能为空");
// 如果希望判断其他逻辑,需要手动编写
Object ageValue = errors.getFieldValue("age");// 获取age属性的值
if(ageValue!=null){
Integer age = Integer.parseInt(ageValue.toString());
if(age<1||age>150){
// rejectValue("校验的属性",“错误码”,"校验不通过时日志打印的消息"):表示属性校验不通过
errors.rejectValue("age",null,"年龄必须是1-150之间的数字");
}
}
}
}
2.3 Test verification results
Write the code in the test class
@Test
void testValidator(){
People people = new People();
DataBinder dataBinder = new DataBinder(people);
dataBinder.setValidator(new MyValidator());
dataBinder.validate();
BindingResult bindingResult = dataBinder.getBindingResult();
bindingResult.getAllErrors().forEach(err->{
System.out.println(err);
});
}
2. Implementation of JSR 303 and Hibernate
2.1 Introduction to JSRs
JCP (Java Community Process) is an international development organization that includes some Java developers and other members who are allowed to join. The JCP organization is mainly responsible for developing and updating the Java community. The specifications maintained include: J2ME, J2SE, J2EE, XML and other related specifications. Members of the organization can submit JSR (Java Specification Requests, Java Specification Proposal), and the relevant content will be added to the next version of the specification after the organization members pass the proposal.
2.2 Introduction to JSR 303
Each JSR proposal has a numerical designation. For example JSR 107, JSR 303, etc. It must be noted that for the JSR proposal, it is not necessary to include the previous content when the number is larger. For example, JSR 107 is mainly a proposal for caching, and JSR 303 is a proposal for data verification. These two proposals do not have a relationship between inclusion and inclusion, and there is no relationship between versions. This is similar to the CPPCC meeting in our country. The suggestion put forward by the first member of the CPPCC is called suggestion 1, and the suggestion put forward by the second member of the CPPCC is called suggestion 2. Suggestion 1 proposes to increase the personal tax threshold, and Suggestion 2 proposes national distribution targets. These two suggestions are irrelevant. JSR 303 is a subspec of the Java EE 6 specification. It's called Bean Validation. These specifications are annotations. Major companies can implement specific implementations of these specifications. The most commonly used JSR 303 implementation in Java development is Hibernate-Validator in the Hibernate framework. It implements all the conventions (constraint) of JSR 303, and also makes certain expansions.
2.3 What Hibernate Validator contains
The Hiberante framework is an ORM framework that was once all the rage in the Java industry. Currently, only some old projects are still in use in enterprises. But there are some nice features in Hibernate that are used all the time. Which includes hibernate-validator. The implementation of hibernate-validator for JSR 303 exists in the javax.validation.constraints package of the dependent Validation-api.jar. All the annotations in it contain the message attribute, which indicates the information printed in the log after the verification fails. But it is not recommended to set it, because the default prompt information is very good. Hibernate Validator's explanation of the specific implementation of JSR 303:
Hibernate-Validator has additional additions to JSR 303, and these annotations are in the org.hibernate.validator.constraints package of Hibernate-validator.jar.
2.4 use of hibernate-validator
add dependencies
In addition to the normal dependencies of the project, additional Hibernate-validator dependencies and EL expression dependencies need to be imported.
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>
<dependency>
<groupId>jakarta.el</groupId>
<artifactId>jakarta.el-api</artifactId>
<version>5.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.el</artifactId>
<version>5.0.0-M1</version>
</dependency>
Add annotations on entity class properties
In the example, NotNull, Length and Range are used as examples.
(1) The message in @NotNull is an optional attribute. If the message is set, the log will print the content of the message after the rule is violated
(2) @Length is to set the string length.
(3) @Range sets the value range. Can be used on int type properties. So name must not be null, and the length is 2-6 digits. The value range of age must be 1~150 Although these annotations can be placed on methods, attributes, other annotations, construction methods, and parameters. We mostly put these annotations on the attributes of the entity class. Each attribute of the entity class supports the configuration of multiple annotations, and these annotations take effect at the same time.
@Data
public class People {
@NotNull(message = "姓名不能是null")
@Length(min = 2,max = 6,message = "长度应该是2-6位")
private String name;
@Range(min=1,max=150)
private int age;
}
Write a test class to test hibernate-validator
@Test
void testHibernateValidator(){
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
People people = new People();
Set<ConstraintViolation<People>> constraintViolations = validator.validate(people);
for (ConstraintViolation<People> constraintViolation : constraintViolations)
{
System.out.println("错误:" + constraintViolation.getMessage());
}
}
Console output information after running
Error: cannot be null
Error: Need to be between 1 and 150
3. Integration of Spring framework to Hibernate-validator
There is a LocalValidatorFactoryBean class in the Spring framework, which implements the ValidatorFactory interface and the Validator interface. So we can directly use this class as the object of Validator instantiation in the Spring framework.
By using LocalValidatorFactoryBean, you can simplify the two lines of code for Hibernate to instantiate the Validator, and the other uses are the same.
public class LocalValidatorFactoryBean extends SpringValidatorAdapter
implements ValidatorFactory, ApplicationContextAware, InitializingBean,
DisposableBean {
3.1 Ensure that the project contains hibernate-validator dependencies
It has been imported when learning Hibernate-validator above
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>
<dependency>
<groupId>jakarta.el</groupId>
<artifactId>jakarta.el-api</artifactId>
<version>5.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.el</artifactId>
<version>5.0.0-M1</version>
</dependency>
3.2 Create a class
Create com.tong.validation.Student, add a few annotations for testing
@Data
public class Student {
@NotBlank
private String name;
@Positive
private int age;
}
3.3 Writing configuration
Create a configuration file applicationContext-validation.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
</bean>
<bean id="student" class="com.tong.validation.Student"></bean>
</beans>
3.4 Writing test classes
Test in com.tong.test.ValidationTest
@SpringJUnitConfig
@ContextConfiguration("classpath:applicationContext-validation.xml")
public class ValidationTest {
@Autowired
LocalValidatorFactoryBean validator;
@Autowired
Student student;
@Test
void test(){
Set<ConstraintViolation<Student>> constraintViolations = validator.validate(student);
for (ConstraintViolation<Student> constraintViolation : constraintViolations) {
System.out.println("错误:" + constraintViolation.getMessage());
}
}
}
3.5 Observing the running results
You can see it in the IDEA console
错误:不能为空
错误:必须是正数