Introduction and introductory case of Hibernate validator

Introduction to hibernate validator

In the early web sites, users input an email address and need to send the email address to the server. The server verifies it and sends a response to the front end after the verification is successful.

With JavaScript, the verification work can be performed on the front end. So why do you need to check the server? Because the data from the front end is not trusted. The front end can easily get the interface of the back end. If someone calls the interface directly, illegal data may appear, so the server also needs data verification.

in general:

  • Front end verification: mainly to improve user experience
  • Back end verification: mainly to ensure the safety and reliability of data

Verifying parameters is basically a manual job, and there are many redundant codes, which also affect the readability of the code. We need a more elegant way to solve this problem. Hibernate Validator framework just solves this problem. It can realize parameter verification in a very elegant way, separate business code from verification logic, and no longer write duplicate verification logic.

Hibernate validator advantages:

  • The verification logic is separated from the business logic, which reduces the coupling degree of the program
  • Unified and standardized verification method, no need for you to write repeated verification code again
  • You will focus more on your business and leave all these cumbersome things aside

maven coordinates of Hibernate validator:

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

Hibernate validator common annotations

The verification method provided by hibernate validator is to add corresponding annotations to the attributes of classes to achieve the purpose of verification. The comments provided by hibernate validator for verification are as follows:

annotationexplain
@AssertTrueUsed for boolean field, which can only be true
@AssertFalseUsed for boolean field, which can only be false
@CreditCardNumberCarry out a general verification of the credit card number
@DecimalMaxCan only be less than or equal to this value
@DecimalMinCan only be greater than or equal to this value
@EmailCheck whether it is a valid email address
@FutureCheck whether the date of this field belongs to the future date
@Length(min=,max=)Check whether the length of the field is between min and max, which can only be used for strings
@MaxThe value of this field can only be less than or equal to this value
@MinThe value of this field can only be greater than or equal to this value
@NotNullCannot be null
@NotBlankCannot be empty, spaces will be ignored when checking
@NotEmptyCannot be empty, where null refers to an empty string
@Pattern(regex=)The annotated element must conform to the specified regular expression
@URL(protocol=,host,port)Check whether it is a valid URL. If protocol, host, etc. are provided, the URL also needs to meet the conditions provided

Introduction case of Hibernate validator

Step 1: create maven project hibernate validator_ Demo and configure pom XML file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>cn.itcast</groupId>
    <artifactId>hibernate-validator_demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!--
		spring-boot-starter-web Has been dependent on hibernate-validator
		-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--
		<dependency>
              <groupId>org.hibernate</groupId>
              <artifactId>hibernate-validator</artifactId>
              <version>6.0.18.Final</version>
        </dependency>
		-->
    </dependencies>
</project>

Note: spring boot starter web already relies on Hibernate validator, so there is no need to import it again.

Step 2: create User class

package cn.itcast.entity;

import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.*;

@Data
public class User {
    @NotNull(message = "user id Cannot be empty")
    private Integer id;

    @NotEmpty(message = "User name cannot be empty")
    @Length(max = 50, message = "User name length cannot exceed 50")
    private String username;

    @Max(value = 80,message = "The maximum age is 80")
    @Min(value = 18,message = "The minimum age is 18")
    private int age;

    @Pattern(regexp = "[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$",
             message = "Email format is incorrect")
    private String email;
}

Step 3: create UserController

package cn.itcast.controller;

import cn.itcast.entity.User;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotBlank;

@RestController
@RequestMapping("/user")
@Validated //Enable the verification function
public class UserController {
    //Simple data type verification
    @RequestMapping("/delete")
    public String delete(@NotBlank(message = "id Cannot be empty") String id){
        System.out.println("delete..." + id);
        return "OK";
    }

    //Object attribute verification
    @RequestMapping("/save")
    public String save(@Validated User user){
        System.out.println("save..." + user);
        return "OK";
    }
}

Step 4: create application yml

server:
  port: 9100

Step 5: create a startup class

package cn.itcast;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HibernateValidatorApp {
    public static void main(String[] args) {
        SpringApplication.run(HibernateValidatorApp.class,args);
    }
}

Start the project, access address: http://localhost:9100/user/save Through the console output, you can see that the data can be verified, as follows:

Field error in object 'user' on field 'age': rejected value [3]; codes [Min.user.age,Min.age,Min.int,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age],18]; default message [The minimum age is 18]]
2020-03-02 16:44:35.504  WARN 14896 --- [nio-9100-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 3 errors
Field error in object 'user' on field 'id': rejected value [null]; codes [NotNull.user.id,NotNull.id,NotNull.java.lang.Integer,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.id,id]; arguments []; default message [id]]; default message [user id Cannot be empty]
Field error in object 'user' on field 'age': rejected value [0]; codes [Min.user.age,Min.age,Min.int,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age],18]; default message [The minimum age is 18]
Field error in object 'user' on field 'username': rejected value [null]; codes [NotEmpty.user.username,NotEmpty.username,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.username,username]; arguments []; default message [username]]; default message [User name cannot be empty]]

The browser page directly reports an error:

Step 6: in order to display the data verification results friendly on the page, you can solve it through global exception handling and create a global exception handling class

package cn.itcast.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

/**
 * Global exception handling
 */
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
public class ExceptionConfiguration {
    @ExceptionHandler({ConstraintViolationException.class,BindException.class})
    public String validateException(Exception ex, HttpServletRequest request) {
        ex.printStackTrace();
        String msg = null;
        if(ex instanceof ConstraintViolationException){
            ConstraintViolationException constraintViolationException = 
                (ConstraintViolationException)ex;
            Set<ConstraintViolation<?>> violations = 
                constraintViolationException.getConstraintViolations();
            ConstraintViolation<?> next = violations.iterator().next();
            msg = next.getMessage();
        }else if(ex instanceof BindException){
            BindException bindException = (BindException)ex;
            msg = bindException.getBindingResult().getFieldError().getDefaultMessage();
        }
        return msg;
    }
}

Restart the program to find that the verification information can be displayed on the page friendly at this time:

From the output of the console, we can see that the verification framework has performed data verification on many of our attributes (the default behavior). If we want to return a prompt directly as long as one attribute fails to verify, how can we implement it if the following attributes are no longer verified?

Step 7: create a ValidatorConfiguration class, and specify the fast failure return mode to be used during verification

package cn.itcast.config;

import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

public class ValidatorConfiguration {
    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = 
            Validation.byProvider(HibernateValidator.class)
                .configure()
                //Quick failure return mode
                .addProperty("hibernate.validator.fail_fast", "true")
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }

    /**
     * Enable quick return
     * If there is an exception in the parameter verification, throw the exception directly, and do not enter the controller. Use global exception interception to intercept
     */
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor postProcessor = 
            new MethodValidationPostProcessor();
        /**Set the validator mode to fast failure return*/
        postProcessor.setValidator(validator());
        return postProcessor;
    }
}

Note: the class created above is not a configuration class, so the quick failure return mode will not take effect so far. In order to make it take effect, you need to create an annotation to control the opening of this mode

Step 8: create an annotation EnableFormValidator to control the opening of the quick failure return mode

package cn.itcast.config;

import org.springframework.context.annotation.Import;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Add this annotation on the startup class to start the form verification function - quick failure return mode
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ValidatorConfiguration.class)
public @interface EnableFormValidator {
}

Step 9: add the EnableFormValidator annotation to the startup class to enable the quick failure return mode

package cn.itcast;

import cn.itcast.config.EnableFormValidator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableFormValidator
public class HibernateValidatorApp {
    public static void main(String[] args) {
        SpringApplication.run(HibernateValidatorApp.class,args);
    }
}

From the output of the console, we can see that although many of the data we entered do not conform to the verification rules, there is only one verification failure exception message, which indicates that the rapid failure return mode has been enabled.

Tags: Java Spring JavaEE Hibernate Validator

Posted by aspbyte on Tue, 19 Jul 2022 05:55:06 +0930