设为首页 加入收藏

TOP

使用 SpringBoot 进行优雅的数据验证(三)
2023-08-26 21:11:14 】 浏览:108
Tags:使用 SpringBoot

@Validated
@Service
public class ValidatorService {

    private static final Logger logger = LoggerFactory.getLogger(ValidatorService.class);

    public String show(@NotNull(message = "不能为空") @Min(value = 18, message = "最小18") String age) {
    	logger.info("age = {}", age);
    	return age;
    }
}

分组校验

有时候对于不同的接口,需要对 DTO 进行不同的校验规则。还是以上面的 UserDTO 为列,另外一个接口可能不需要将 age 限制在 18 ~ 50 之间,只需要大于 18 就可以了。

这样上面的校验规则就不适用了。分组校验就是来解决这个问题的,同一个 DTO,不同的分组采用不同的校验策略。

public class UserDTO {

    public interface Default {
    }

    public interface Group1 {
    }

    private Integer userId;
    //注意:@Validated 注解中加上groups属性后,DTO中没有加group属性的校验规则将失效
    @NotEmpty(message = "姓名不能为空",groups = Default.class)
    private String name;

    //注意:加了groups属性之后,必须在@Validated 注解中也加上groups属性后,校验规则才能生效,不然下面的校验限制就失效了
    @Range(min = 18, max = 50, message = "年龄必须在18和50之间",groups = Default.class)
    @Range(min = 17, message = "年龄必须大于17", groups = Group1.class)
    private Integer age;

}

使用方式

@PostMapping("/saveUserGroup")
@ResponseBody
//注意:如果方法中的参数是对象类型,则必须要在参数对象前面添加 @Validated
//进行分组校验,年龄满足大于 17
public Response<UserDTO> saveUserGroup(@Validated(value = {UserDTO.Group1.class}) @RequestBody UserDTO userDTO){
    userDTO.setUserId(100);
    Response response = Response.success();
    response.setData(userDTO);
    return response;
}

使用 Group1 分组进行校验,因为 DTO 中,Group1 分组对 name 属性没有校验,所以这个校验将不会生效。

分组校验的好处是可以对同一个 DTO 设置不同的校验规则,缺点就是对于每一个新的校验分组,都需要重新设置下这个分组下面每个属性的校验规则。

分组校验还有一个按顺序校验功能。

考虑一种场景:一个 bean 有 1 个属性(假如说是 attrA),这个属性上添加了 3 个约束(假如说是@NotNull、@NotEmpty、@NotBlank)。默认情况下,validation-api 对这 3 个约束的校验顺序是随机的。也就是说,可能先校验@NotNull,再校验@NotEmpty,最后校验@NotBlank,也有可能先校验@NotBlank,再校验@NotEmpty,最后校验@NotNull。

那么,如果我们的需求是先校验@NotNull,再校验@NotBlank,最后校验@NotEmpty。@GroupSequence 注解可以实现这个功能。

public class GroupSequenceDemoForm {

    @NotBlank(message = "至少包含一个非空字符", groups = {First.class})
    @Size(min = 11, max = 11, message = "长度必须是11", groups = {Second.class})
    private String demoAttr;

    public interface First {

    }

    public interface Second {

    }

    @GroupSequence(value = {First.class, Second.class})
    public interface GroupOrderedOne {
        // 先计算属于 First 组的约束,再计算属于 Second 组的约束
    }


    @GroupSequence(value = {Second.class, First.class})
    public interface GroupOrderedTwo {
        // 先计算属于 Second 组的约束,再计算属于 First 组的约束
    }

}

使用方式

// 先计算属于 First 组的约束,再计算属于 Second 组的约束
@Validated(value = {GroupOrderedOne.class}) @RequestBody GroupSequenceDemoForm form

嵌套校验

前面的示例中,DTO 类里面的字段都是基本数据类型和 String 等类型。

但是实际场景中,有可能某个字段也是一个对象,如果我们需要对这个对象里面的数据也进行校验,可以使用嵌套校验。

假如 UserDTO 中还用一个 Job 对象,比如下面的结构。需要注意的是,在 job 类的校验上面一定要加上@Valid 注解。

public class UserDTO1 {

    private Integer userId;
    @NotEmpty
    private String name;
    @NotNull
    private Integer age;
    @Valid
    @NotNull
    private Job job;

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Job getJob() {
        return job;
    }

    public void setJob(Job job) {
        this.job = job;
    }

    /**
     * 这边必须设置成静态内部类
     */
    static class Job {
        @NotEmpty
        private String jobType;
        @DecimalMax(value = "1000.99")
        pri
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 3/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇记录一次解决数据库连接池连接泄.. 下一篇Tomcat+Eclipse乱码问题解决方法

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目