SpringBoot——JSR303校验
我们在写代码中,前端请求后端接口传输参数必须要进行参数校验:
Contoller
- 校验请求参数的合法性,包括:必填项校验,数据格式校验,比如:是否是符合一定的日期格式,等。
Service
- 校验的是业务规则相关的内容,比如:课程已经审核通过所以提交失败。
SpringBoot提供了JSR-303的支持,它就是spring-boot-starter-validation。
它的底层使用HibernateValidator,Hibernate Validator是Bean Validation 的参考实现。
所以,我们准备在Controller层使用spring-boot-starter-validation完成对请求参数的基本合法性进行校验。
maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
现在准备对内容管理模块添加课程接口进行参数校验,如下接口:
@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody AddCourseDto addCourseDto){
return courseBaseInfoService.createCourseBase(companyId,addCourseDto);
}
此接口使用AddCourseDto模型对象接收参数,所以进入AddCourseDto类,在属性上添加校验规则。
/**
* @description 添加课程dto
* @author anqin
* @date 2022/9/7 17:40
* @version 1.0
*/
@Data
public class AddCourseDto {
@NotEmpty(message = "课程名称不能为空",groups = GroupCheck.Insert.class)
@NotEmpty(message = "课程名称不能为空",groups = GroupCheck.Update.class)
private String name;
@NotEmpty(message = "适用人群不能为空")
@Size(message = "适用人群内容过少",min = 10)
private String users;
@NotEmpty(message = "课程分类不能为空")
private String mt;
@NotEmpty(message = "课程分类不能为空")
private String st;
@NotEmpty(message = "收费规则不能为空")
private String charge;
}
上边用到了@NotEmpty和@Size两个注解,@NotEmpty表示属性不能为空,@Size表示限制属性内容的长短。
在javax.validation.constraints包下有很多这样的校验注解:
规则如下:
定义好校验规则还需要开启校验,在controller方法中添加@Validated注解,如下:
@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody @Validated AddCourseDto addCourseDto){
return courseBaseInfoService.createCourseBase(companyId,addCourseDto);
}
如果校验出错Spring会抛出MethodArgumentNotValidException异常,我们需要在统一异常处理器中捕获异常,解析出异常信息。
/**
* @author anqin
* @version 1.0
* @description 全局异常处理器
* @date 2022/9/6 11:29
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* @ResponseBody 返回json
*/
@ResponseBody
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestErrorResponse doValidException(MethodArgumentNotValidException argumentNotValidException) {
BindingResult bindingResult = argumentNotValidException.getBindingResult();
StringBuffer errMsg = new StringBuffer();
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
fieldErrors.forEach(error -> {
errMsg.append(error.getDefaultMessage()).append(",");
});
log.error(errMsg.toString());
return new RestErrorResponse(errMsg.toString());
}
}
/**
* @author anqin
* @version 1.0
* @description 通用错误信息
* @date 2022/9/6 11:29
*/
public enum CommonError {
UNKNOWN_ERROR("执行过程异常,请重试。"),
PARAMS_ERROR("非法参数"),
OBJECT_NULL("对象为空"),
QUERY_NULL("查询结果为空"),
REQUEST_NULL("请求参数为空");
private String errMessage;
public String getErrMessage() {
return errMessage;
}
private CommonError(String errMessage) {
this.errMessage = errMessage;
}
}
执行测试,接口响应结果如下:
{
"errMessage": "课程名称不能为空 课程分类不能为空 课程分类不能为空 适用人群内容过少 "
}
分组校验
有时候在同一个属性上设置一个校验规则不能满足要求,比如:订单编号由系统生成,在添加订单时要求订单编号为空,在更新 订单时要求订单编写不能为空。
此时就用到了分组校验,同一个属性定义多个校验规则属于不同的分组,比如:
添加订单定义@NULL规则属于insert分组,更新订单定义@NotEmpty规则属于update分组,insert和update是分组的名称,是可以修改的。
如:
/**
* @ClassName: GroupCheck
* @author: anqin
* @Description: 分组校验
* @date: 2023/1/31 21:49
*/
public class GroupCheck {
public interface Insert{};
public interface Update{};
public interface Delete{};
}
下边在定义校验规则时指定分组:
@NotEmpty(message = "课程名称不能为空",groups = GroupCheck.Insert.class)
@NotEmpty(message = "课程名称不能为空",groups = GroupCheck.Update.class)
private String name;
在Controller方法中启动校验规则指定要使用的分组名:
@MonitorExecTime(description = "新增课程接口")
@RequestMapping(value = "/course", method = RequestMethod.POST)
public CourseBaseInfoDto createCourseBase(@RequestBody
@Validated(value = GroupCheck.Insert.class) AddCourseDto addCourseDto) {
return courseBaseService.createCourseBase(addCourseDto);
}
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果