SpringBoot2 | 第二十六篇(三):分组验证

​ 前面两章中详细介绍了 数据验证自定义验证。本章是数据验证的最后一篇,对分组校验做了笔记

[TOC]

分组验证

有的时候,我们对一个实体类需要有多中验证方式,在不同的情况下使用不同验证方式,比如说对于一个实体类来的 id 来说,新增的时候是不需要的,对于更新时是必须的,这个时候你是选择写一个实体类呢还是写两个呢?

在上一篇中介绍到注解需要有一个 groups 属性,这个属性的作用又是什么呢?

接下来就让我们看看如何用一个验证类实现多个接口之间不同规则的验证

环境/版本一览:

  • 开发工具:Intellij IDEA 2018.2.2
  • springboot: 2.1.0.RELEASE
  • jdk:1.8.0_171
  • maven:3.3.9

1、pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

2、application.yml

1
2
server:
port: 8088

3、groups

分组验证器

定义一个验证组,里面写上不同的空接口类即可

groups 属性的作用就让 @Validated 注解只验证与自身 value 属性相匹配的字段,可多个,只要满足就会去纳入验证范围;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.fatal.groups;

/**
* 自定义验证组(作用有点像标记)
* 更新的时候,需要校验全部属性,所以不需要给它分组,新增的时候只需校验部分属性,所以可以给它分组
* @author: Fatal
* @date: 2018/11/28 0028 15:23
*/
public class Groups {

public interface Insert {}

public interface Update {}

/**
* Update组中,可以为null且不能为空的属性,在Other中不能为空
*/
public interface Other {}


}

4、entity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.fatal.entity;

import com.fatal.groups.Groups;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
* Book 实体
* @author: Fatal
* @date: 2018/11/28 0028 15:23
*/
@Data
public class Book {

@NotNull(message = "id 不能为空", groups = Groups.Update.class)
private Long id;

/**
* 纸的质量
* @desc 更新的时候可以填充,要么不填(可以为null),要填就不能为空(空串)
* 更新的属性中,很多需要这么校验,可以为 null,但不能为空
*/
@Length(min = 1, message = "paperQuality 不能为空", groups = Groups.Update.class)
@NotBlank(message = "paperQuality 不能为空", groups = Groups.Other.class)
private String paperQuality;

/**
* 页码
*/
@Min(value = 200, message = "email 不能为空", groups = Groups.Update.class)
private Integer pageNumber;

/**
* 书名
*/
@NotBlank(message = "name 不能为空", groups = {Groups.Insert.class, Groups.Update.class})
private String name;

/**
* 价格
*/
@NotNull(message = "price 不能为空", groups = {Groups.Insert.class, Groups.Update.class})
private Long price;

}

5、controller

  • insert:所有属性为必填
  • update:与insert的属性交集为必填,其它属性可以为 null(用户没填充嘛),如果不为 null 的话就必须接受其它校验(如:String 长度最小为 1,Integer 最小值为 200 等等)
  • other:部分属性为必填
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.fatal.controller;

import com.fatal.entity.Book;
import com.fatal.groups.Groups;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @author: Fatal
* @date: 2018/11/28 0028 15:27
*/
@RestController
public class ValidatorController {

@PostMapping(value = "/insert")
public String insert(@Validated(value = Groups.Insert.class) Book book,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return bindingResult.getFieldError().getDefaultMessage();
}
return "success";
}

@PostMapping(value = "/update")
public String update(@Validated(value = Groups.Update.class) Book book,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return bindingResult.getFieldError().getDefaultMessage();
}
return "success";
}

@PostMapping(value = "/other")
public String other(@Validated(value = Groups.Other.class) Book book,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return bindingResult.getFieldError().getDefaultMessage();
}
return "success";
}

}

显示

启动项目

可以使用 IDEA 自带的 RestClient 测试,也可以使用 Postman 测试

  1. 访问 http://localhost:8088/insert

    1565575549594

    1565575396762

  2. 访问 http://localhost:8088/update

    • 填充 paperQualitypageNumber

      1565576324558

      1565575643786

    • 不填充paperQualitypageNumber

      1565576526170

      1565576382701

  3. 访问 http://localhost:8088/other

    1565576744723

    1565576634555

参考资料

一起来学SpringBoot | 第二十一篇:轻松搞定数据验证(三)

总结

update 的属性必须包括insert的属性,要不然你update的时候,传了insert的属性,那么insert的属性就没有参与校验了,这不合逻辑。所以呢?解决方法两种:

  1. update方法上参数位置的 @Validated的值两个都加上(只有两组的话,而且刚好互为补集的话你可以这么用,否则用下面这一种)
  2. 数据传输对象中,所有的校验注解的 groups属性两个都加上(推荐

源码地址: https://github.com/ynfatal/springboot2-learning/tree/master/chapter26_3

学习 唐亚峰 前辈的经验