@valid group verification, manually trigger valid verification

Business scenario: 同一个接口,不同的操作when the time, check the field is different. For example, when the status is changed, when the fields to be verified are different for leave application approval and cancellation.
However, the conventional @valid annotation is unsatisfactory (parameter interception when requesting, triggering validation rules). And my business scenario must manually trigger @valid verification

Not much nonsense, the following directly shows the ideas and core related codes

1. Design ideas

In essence, the reason why the conventional @Valid does not meet the requirements is:
1. The same interface triggers different group field verification according to the type field;
2. Manually triggers the valid group verification.
Supplement: What I mean by regular @valid is @Validated(value = {People.Student.class}), the code is as follows:

    /**
     * <p>@Description: 请求拦截-根据分组进行参数校验 </p >
     * <p>@param [people]</p >
     * <p>@return com.lzq.learn.domain.CommonResult</p >
     * <p>@throws </p >
     * <p>@date 14:37 14:37</p >
     */
    @PostMapping("validByGroup")
    public CommonResult validByGroup(@RequestBody @Validated(value = {
    
    People.Student.class}) People people) {
    
    
        System.out.println("People 参数:" + people);
        CommonResult commonResult = CommonResult.success(people);
        return commonResult;
    }

2. Complete code display

2.1 controller code

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.lzq.learn.domain.CommonResult;
import com.lzq.learn.domain.People;
import com.lzq.learn.domain.User;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.*;
import javax.validation.groups.Default;
import java.util.List;
import java.util.Set;

@RestController
@RequestMapping("valid")
public class TestValidController {
    
    


    @Autowired
    private Validator validator;

    /**
     * <p>@Description: 测试手动触发valid分组校验</p >
     * <p>@param [userList]</p >
     * <p>@return com.lzq.learn.domain.CommonResult</p >
     * <p>@throws </p >
     * <p>@date 15:21 15:21</p >
     */
    @PostMapping("validByHand")
    public CommonResult validByHand(@RequestBody People people) {
    
    
        System.out.println("people  参数:" + people);
        String validResult = "";
        List<Class> groupList = CollUtil.newArrayList(Default.class);
        if (StrUtil.equals("student", people.getType())) {
    
    
            groupList.add(People.Student.class);
        }
        if (StrUtil.equals("teacher", people.getType())) {
    
    
            groupList.add(People.Teacher.class);
        }
        Class[] groupArray = groupList.toArray(new Class[groupList.size()]);
        // 写法1:使用ValidatorFactory 获取Validator对象
        Set<ConstraintViolation<People>> violations = Validation.buildDefaultValidatorFactory().getValidator().validate(people, groupArray);
        // 写法2:从springboot上下文 获取Validator对象
        // Set<ConstraintViolation<People>> violations = validator.validate(people, groupArray);
        validResult = getResultFromValidate(violations);
        CommonResult commonResult = CommonResult.success(validResult);
        return commonResult;
    }


    /**
     * <p>@Description: 对于valid校验结果进行转换结果</p >
     * <p>@param </p >
     * <p>@return </p >
     * <p>@throws </p >
     * <p>@date 13:43 13:43</p >
     */
    public static <T> String getResultFromValidate(Set<ConstraintViolation<T>> violations) {
    
    
        if (CollUtil.isEmpty(violations)) {
    
    
            return "pass";
        }
        StringBuilder sb = new StringBuilder();
        for (ConstraintViolation<T> violation : violations) {
    
    
            sb.append(violation.getPropertyPath()).append(": ").append(violation.getMessage()).append("\n");
        }
        return sb.toString();
    }
    
}

注意:We need to trigger it manually, so we cannot add @valid (or @validated) annotations to the interface of the controller, otherwise the request will be intercepted and we will not be able to enter our controller code at all!

2.2 Entity class People code


import lombok.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

/**
 * @author x
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class People implements Serializable {
    
    

    /**     自定义校验分组        **/
    public interface Student{
    
    }
    public interface Teacher{
    
    }

    private Long id;

    @NotNull(message = "年龄不能为空")
    private Integer age;

    @NotBlank(message = "个人名称不能为空")
    private String myName;

    @NotBlank(message = "学生名称不能为空", groups = Student.class)
    private String studentName;

    @NotBlank(message = "教师名称不能为空", groups = Teacher.class)
    private String teacherName;

    // dto 字段
    private String type;
}

Note: For this entity class, the age and myName fields do not specify groups, but they are actually assigned to Default.classgroups (javax.validation.groups.Default)

3. postMan interface test

For a brief overview, this article only conducts test analysis for the case of type=student. According to the above code, when type=student, the group verification of Default and Student will be performed, as shown in the postman interface test as shown below

3.1 type=student, do not pass the default group field

insert image description here

3.1 type=student, do not pass the student group field

insert image description here

3.1 type=student, do not pass the teacher group field

insert image description here

3.1 type=student, all group fields are passed

insert image description here

As shown in the figure, we found that the code we wrote is correct, and it has realized 任意代码执行顺序the self-defined group verification according to the type. But the controller interface must not be annotated with @valid or @validated, 不然请求会被拦截and it will not reach our custom method at all.

This blog also just changed the execution timing of valid parameter verification. In fact, the above code only provides the most basic solution, which can be optimized to add custom annotations to the method to realize aop parameter verification interception! Abstract this behavior to avoid repetitive if else code redundancy.

Guess you like

Origin blog.csdn.net/lzq2357639195/article/details/131259458