Spring Boot基于javax.validation进行参数校验

在我们使用Spring Boot开发Web Api的时候,肯定会少不了参数校验,一般情况下,大部分是使用if来判断参数是否合法,在参数较少的情况下,这样做除了少量的重复工作外,也没有较大的工作量。但是当遇到一个复杂的参数的时候,可能整个方法大部分的代码都是if。工作量大不说,代码也精简。那么有没有更好的方式来处理呢?这就是我们这里要说到的参数校验技巧。

为了体现说明,我们事先创建好一个StudentVO类和一个StudentController.在StudentVO中加入几个简单的属性,仅做展示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@ApiModel("StudentVO")
@Data
public class StudentVO {

@ApiModelProperty("学生名字")
private String name;

@ApiModelProperty("学生年龄")
private Integer age;

@ApiModelProperty("学生住址")
private String address;
}

这里@ApiModelProperty@ApiModel注解是我用了Swagger,你们可以直接写注释即可。为了减少GetterSetter的工作量,我们引入了lombok工具包:

1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>

这里需要注意的是,需要给IDE安装插件,因为我是用的IDEA所以插件安装很方便:Settings->Plugins,搜索lombok插件点击Install即可,安装完成后有个Restart IDE的按钮,点击重启即可。
接下来,我们来进入示例环节,开始编码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RequestMapping("/v1/student")
@RestController
@Api(value = "Student API展示")
public class StudentController {
@PostMapping("/CreateStudent")
public ResponseEntity<String> CreateStudent(StudentVO studentVO)
{
if(StringUtils.isEmpty(studentVO.getName()))
return new ResponseEntity<>("学生名字不能为空", HttpStatus.OK);
if(studentVO.getAge()>=5&&studentVO.getAge()<=30)
return new ResponseEntity<>("学生年龄不能大于30岁或者小于5岁", HttpStatus.OK);
if(StringUtils.isEmpty(studentVO.getName()))
return new ResponseEntity<>("学生住址不能为空", HttpStatus.OK);
return new ResponseEntity<>("Success", HttpStatus.OK);
}
}

可以看到,目前这个vo类只有三个属性,在我们的action中也写了许多的用于校验的if,我们来看一下效果:


当我们的属性有几十个的时候,还继续使用if来检验参数,确实是一件比较痛苦的事情,成了完全的手工活,而且还有可能会出错,为了提高我们的开发效率,自然得让一个工具来解决这个参数校验的问题,在我使用的Spring Boot2.2.1中已经为我们引入了javax.validation:

1
2
3
4
5
6
7
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${javax-validation.version}</version>
</dependency>

<javax-validation.version>2.0.1.Final</javax-validation.version>

那么我们就可以直接使用validation-api,在使用之前,我们需要先熟悉几个注解:

  • @AssertFalse 用于boolean字段,只能为true
  • @AssertFalse 用于boolean字段,只能为false
  • @DecimalMax(value=x)验证注解的元素值小于等于指定的value值
  • @DecimalMin(value=x)验证注解的元素值大于等于指定的value值
  • @Digits(integer=整数位数, fraction=小数位数) 验证注解的元素值必须是数值
  • @Email 验证注解的元素值是电子邮件地址
  • @Future(integer=整数位数, fraction=小数位数) 验证注解的元素值(日期类型)比当前时间晚
  • @FutureOrPresent(integer=整数位数, fraction=小数位数)验证注解的元素值(日期类型)比当前时间晚或者等于当前时间
  • @Past 验证注解的元素值(日期类型)比当前时间早
  • @ScriptAssert(lang= ,script=, alias=)
  • @URL(protocol=,host=, port=,regexp=, flags=) URL验证
  • @PastOrPresent验证注解的元素值(日期类型)比当前时间早或等于现在
  • @Max(value=x)验证注解的元素值小于等于指定的value值
  • @Mix(value=x)验证注解的元素值大于等于指定的value值
  • @NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
  • @NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
  • @NotNull 验证注解的元素值不是null
  • @CreditCardNumber 信用卡验证
  • @Null 验证注解的元素值是null
  • @Pattern(regex=正则表达式, flag=) 验证注解的元素值与指定的正则表达式匹配
  • @Size(min=最小值, max=最大值) 验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小
    我们就可以参照这些注解来校验参数:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @ApiModel("StudentVO")
    @Data
    public class StudentVO {

    @NotEmpty(message ="学生名字不能为空")
    @ApiModelProperty("学生名字")
    private String name;

    @Range(min = 5, max = 30, message = "学生年龄不能大于30岁或者小于5岁")
    @ApiModelProperty("学生年龄")
    private Integer age;

    @NotEmpty(message ="学生住址不能为空")
    @ApiModelProperty("学生住址")
    private String address;
    }
    修改StudentController:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @RequestMapping("/v1/student")
    @RestController
    @Api(value = "Student API展示")
    public class StudentController {
    @PostMapping("/CreateStudent")
    public ResponseEntity<String> CreateStudent(@Valid StudentVO studentVO, BindingResult validResult)
    {
    if(validResult.hasErrors())
    return new ResponseEntity<>(validResult.getAllErrors().get(0).getDefaultMessage(), HttpStatus.OK);

    // if(StringUtils.isEmpty(studentVO.getName()))
    // return new ResponseEntity<>("学生名字不能为空", HttpStatus.OK);
    // if(studentVO.getAge()>=5&&studentVO.getAge()<=30)
    // return new ResponseEntity<>("学生年龄不能大于30岁或者小于5岁", HttpStatus.OK);
    // if(StringUtils.isEmpty(studentVO.getName()))
    // return new ResponseEntity<>("学生住址不能为空", HttpStatus.OK);
    return new ResponseEntity<>("Success", HttpStatus.OK);
    }
    }
    最后效果
You forgot to set the qrcode for Alipay. Please set it in _config.yml.
You forgot to set the qrcode for Wechat. Please set it in _config.yml.
You forgot to set the business and currency_code for Paypal. Please set it in _config.yml.
You forgot to set the url Patreon. Please set it in _config.yml.
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×