校验的需求
前端请求后端接口传输参数,需要校验参数。
- 在controller中需要校验参数的合法性,包括:必填项校验、数据格式校验等
- 在service中需要校验业务规则,比如:课程已经审核过了,所以提交失败。
service中的业务规则不方便写成通用的代码,但是controller中的可以。
JSR-303定义了参数校验的规范,对bean属性进行校验。spring boot提供了JSR-303支持,即spring-boot-starter-validation
。
导入相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
在javax.validation.constraints
包下有很多这样的校验注解,直接使用注解定义校验规则即可
实现
定义校验规则
@Data
public class AddCourseDto {
@NotEmpty(message = "课程名称不能为空")
@ApiModelProperty(value = "课程名称", required = true)
private String name;
@NotEmpty(message = "适用人群不能为空")
@Size(message = "适用人群内容过少",min = 10)
@ApiModelProperty(value = "适用人群", required = true)
private String users;
@ApiModelProperty(value = "课程标签")
private String tags;
@NotEmpty(message = "课程分类不能为空")
@ApiModelProperty(value = "大分类", required = true)
private String mt;
......
开启校验
在controller方法中添加@Validated注解,开启校验
@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody @Validated AddCourseDto addCourseDto) {
Long companyId = 114514L;
return courseBaseInfoService.createCourseBase(companyId, addCourseDto);
}
如果校验出错Spring会抛出MethodArgumentNotValidException异常,我们需要在统一异常处理器中捕获异常,解析出异常信息。
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestErrorResponse exception(MethodArgumentNotValidException e) {
BindingResult result = e.getBindingResult();
List<String> msgList = new ArrayList<>();
result.getFieldErrors().stream().forEach(item -> msgList.add(item.getDefaultMessage()));
String msg = StringUtils.join(msgList, ",");
log.error("【系统异常】{}", msg);
return new RestErrorResponse(msg);
}
测试
把必选项设置为空,发送请求。
略…
分组校验
有时在同一个属性上设置一个校验规则不能满足要求。
比如:订单编号在添加时要求为空,在修改时要求不为空。此时就需要用到分组校验,同一个属性定义多个校验规则属于不同的分组。
比如@NULL
规则属于insert分组,@NotEmpty
规则属于update分组。
实现
定义分组
用class类表示不同的分组,定义不同的接口类型表示不同的分组。
public class ValidationGroups {
public interface Insert{};
public interface Update{};
public interface Delete{};
}
在定义校验规则时指定分组
@NotEmpty(groups = {ValidationGroups.Insert.class}, message = "添加课程名称不能为空")
@NotEmpty(groups = {ValidationGroups.Update.class}, message = "修改课程名称不能为空")
@ApiModelProperty(value = "课程名称", required = true)
private String name;
在Controller方法中启动校验规则指定要使用的分组名
@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody @Validated({ValidationGroups.Insert.class}) AddCourseDto addCourseDto) {
Long companyId = 114514L;
return courseBaseInfoService.createCourseBase(companyId, addCourseDto);
}
校验规则不满足使用条件
- 手写校验代码
- 自定义校验规则注解(查阅相关资料)