Spring 6 [Data Validation Validation, JSR 303 and Hibernate Implementation] (13) - Comprehensive Detailed Explanation (Learning Summary --- From Introduction to Deepening)

 

Table of contents

Data verification Validation

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

错误:不能为空
错误:必须是正数

Guess you like

Origin blog.csdn.net/m0_58719994/article/details/132000508