在我们使用Spring Boot开发Web Api的时候,肯定会少不了参数校验,一般情况下,大部分是使用if
来判断参数是否合法,在参数较少的情况下,这样做除了少量的重复工作外,也没有较大的工作量。但是当遇到一个复杂的参数的时候,可能整个方法大部分的代码都是if
。工作量大不说,代码也精简。那么有没有更好的方式来处理呢?这就是我们这里要说到的参数校验技巧。
为了体现说明,我们事先创建好一个StudentVO
类和一个StudentController
.在StudentVO
中加入几个简单的属性,仅做展示:
1 | import io.swagger.annotations.ApiModel; |
这里@ApiModelProperty
和@ApiModel
注解是我用了Swagger
,你们可以直接写注释即可。为了减少Getter
、Setter
的工作量,我们引入了lombok
工具包:
1 | <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> |
这里需要注意的是,需要给IDE安装插件,因为我是用的IDEA所以插件安装很方便:Settings->Plugins
,搜索lombok
插件点击Install即可,安装完成后有个Restart IDE
的按钮,点击重启即可。
接下来,我们来进入示例环节,开始编码:
1 | @RequestMapping("/v1/student") |
可以看到,目前这个vo类只有三个属性,在我们的action中也写了许多的用于校验的if
,我们来看一下效果:
当我们的属性有几十个的时候,还继续使用if
来检验参数,确实是一件比较痛苦的事情,成了完全的手工活,而且还有可能会出错,为了提高我们的开发效率,自然得让一个工具来解决这个参数校验的问题,在我使用的Spring Boot2.2.1中已经为我们引入了javax.validation
:
1 | <dependency> |
那么我们就可以直接使用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);
}
}