其他分享
首页 > 其他分享> > 统一校验

统一校验

作者:互联网

此文代码托管地址: https://gitee.com/ZomiCC/code/tree/master/validate

我们平时都会碰到很多通用校验的场景:比如字段非空校验、字段长度校验等等。如下所示:

两种校验方式

一、@Validated + BindingResult controller校验

请求实体与BindingResult一一对应。
依赖的注解:

展开
        <!-- valid校验 -->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        <!-- 想要BindResult生效,这个依赖一定要有 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
实体类:
点击查看代码
@Data
@ToString
public class ReqDTO {
    @NotBlank(message = "param1不能为空")
    private String param1;
    @NotBlank(message = "param2不能为空")
    private String param2;
    @NotBlank(message = "param3不能为空")
    private String param3;
}
controller:
点击查看代码
    @PostMapping("/param1")
    public String param1(@Validated @RequestBody ReqDTO reqDTO, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            assert fieldError != null;
            return fieldError.getDefaultMessage();
        }
        return "success";
    }
验证效果: 请求

响应

二、自定义Validator校验工具类

不局限于controller层,在任何地方都可以使用。
工具类:

点击查看代码
package com.example.validate.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Component
public class ParamCheckUtil {
    private static Validator validator;
    @Autowired
    private Validator injectValidator;

    @PostConstruct
    public void preInit() {
        validator = injectValidator;
    }

    public static <T> String checkByGroupsGetOneMessage(T t, Class<?>... groups) {
        if (t == null) {
            return null;
        }
        Set<ConstraintViolation<T>> validate = validator.validate(t, groups);
        if (validate.size() == 0) {
            return null;
        }
        return validate.stream().findFirst().get().getMessage();
    }

    public static <T> String checkByGroupsGetAllMessage(T t, Class<?>... groups) {
        if (t == null) {
            return null;
        }
        Set<ConstraintViolation<T>> validate = validator.validate(t, groups);
        if (validate.size() == 0) {
            return null;
        }
        List<String> msgList = new ArrayList<>();
        validate.forEach(cv -> msgList.add(cv.getMessage()));
        return String.join(";", msgList);
    }
}

应用举例:
点击查看代码
    @PostMapping("/param2")
    public String param2(@RequestBody ReqDTO reqDTO) {
        String message = ParamCheckUtil.checkByGroupsGetAllMessage(reqDTO);
        if (message != null) {
            return message;
        }
        return "success";
    }

其他扩展校验

一、分组校验

当一个实体类应用于多个场景的请求入参时,对入参要求又不一样,我们没必要每次都新建一个冗余的实体类。那怎么办呢,可以给校验属性添加上分组。默认分组是Default。
实体类:

点击查看代码
@Data
@ToString
public class GroupReqDTO {
    @NotBlank(message = "param1不能为空")
    private String param1;
    @NotBlank(message = "param2不能为空", groups = A.class)
    private String param2;
    @NotBlank(message = "param3不能为空", groups = B.class)
    private String param3;

    public interface A {}
    public interface B {}
}
controller:
点击查看代码
    @PostMapping("/param4")
    public String param4(@Validated({GroupReqDTO.A.class}) @RequestBody GroupReqDTO reqDTO, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            assert fieldError != null;
            return fieldError.getDefaultMessage();
        }
        return "success";
    }

二、嵌套校验

当存在嵌套引用对象时,可以使用嵌套校验。嵌套类型需要使用@Valid注解标识。
实体类:

点击查看代码
@Data
public class NestedReqDTO {
    @NotBlank(message = "param1不能为空")
    private String param1;
    @NotBlank(message = "param2不能为空")
    private String param2;
    @NotBlank(message = "param3不能为空")
    private String param3;
    @Valid
    @NotNull(message = "param4不能为空")
    private OtherEntity param4;

    @Data
    class OtherEntity {
        @NotBlank(message = "属性1不能为空")
        private String property1;
    }
}
controller:
点击查看代码
    @PostMapping("/param5")
    public String param5(@Validated @RequestBody NestedReqDTO reqDTO, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            assert fieldError != null;
            return fieldError.getDefaultMessage();
        }
        return "success";
    }

三、复杂关联校验

借助DefaultGroupSequenceProvider,可以实现属性间依赖关系的复杂校验。具体实现参考如下代码:
实体类:

点击查看代码
@Data
@ToString
@GroupSequenceProvider(MyGroupSequenceProvider.class)
public class MutiReqDTO {
    @NotBlank(message = "param1不能为空")
    private String param1;
    @NotBlank(message = "param2不能为空")
    private String param2;
    @NotBlank(message = "当param2为1时,param3不能为空", groups = Param2.class)
    private String param3;

    public interface Param2 {}
}

分组配置器:

点击查看代码
public class MyGroupSequenceProvider implements DefaultGroupSequenceProvider<MutiReqDTO> {
    @Override
    public List<Class<?>> getValidationGroups(MutiReqDTO mutiReqDTO) {
        List<Class<?>> classes = new ArrayList<>();
        classes.add(MutiReqDTO.class);
        if (mutiReqDTO == null) {
            return classes;
        }
        // 如果param2参数为“1”,则需要校验param3
        if ("1".equals(mutiReqDTO.getParam2())) {
            classes.add(MutiReqDTO.Param2.class);
        }
        return classes;
    }
}

controller测试:

点击查看代码
    @PostMapping("/param3")
    public String param3(@RequestBody MutiReqDTO reqDTO) {
        String message = ParamCheckUtil.checkByGroupsGetAllMessage(reqDTO);
        if (message != null) {
            return message;
        }
        return "success";
    }

验证效果:

标签:return,String,校验,private,为空,message,public,统一
来源: https://www.cnblogs.com/zomicc/p/16652157.html