SpringBoot 数据校验
在项⽬开发中,对于前端提交的表单,后台接⼝接收到表单数据后,为了保证程序的严谨性,通常后端会加⼊业务参数的合法校验操作来避免程序的⾮技术性 bug,这⾥对于客户端提交的数据校验,SpringBoot 通过 spring-boot-starter-validation 模块包含了数据校验的⼯作。
1、使用
- 引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
- 了解相关注解的功能
@Null 验证对象是否为null @NotNull 验证对象是否不为null, 无法查检长度为0的字符串 @NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格. @NotEmpty 检查约束元素是否为NULL或者是EMPTY. Booelan检查 @AssertTrue 验证 Boolean 对象是否为 true @AssertFalse 验证 Boolean 对象是否为 false 长度检查 @Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内 @Length(min=, max=) Validates that the annotated string is between min and max included. 日期检查 @Past 验证 Date 和 Calendar 对象是否在当前时间之前 @Future 验证 Date 和 Calendar 对象是否在当前时间之后 @Pattern 验证 String 对象是否符合正则表达式的规则 数值检查,建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为"",Integer为null @Min 验证 Number 和 String 对象是否大等于指定的值 @Max 验证 Number 和 String 对象是否小等于指定的值 @DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度 @DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度 @Digits 验证 Number 和 String 的构成是否合法 @Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。 @Range(min=, max=) 检查数字是否介于min和max之间. @Range(min=10000,max=50000,message="range.bean.wage") private BigDecimal wage; @Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证) @CreditCardNumber 信用卡验证 @Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。 @ScriptAssert(lang= ,script=, alias=) @URL(protocol=,host=, port=,regexp=, flags=)
- 代码中使用
实体类/接收参数类
@Data public class User { @NotNull(message = "id不能为空") private Long id; @NotEmpty(message = "姓名不能为空") @Length(min = 2,message = "姓名不能小于两位") private String name; @Min(value = 16,message = "年龄必须大于16") private int age; }
仅仅这样是不会起作用的,接下来要在使用上述类的接口方法中使用** _@Validated **注解_
@PostMapping("/search") public Result search(@RequestBody @Validated User user) { return taskService.findTaskAuditByFilter(user); }
如果是使用RESTful风格,那么就按照下面这种形式写
@RestController @RequestMapping("/audit") @Validated public class AuditController { @Autowired private TaskService taskService; @PostMapping("/pass/{id}") public Result pass(@PathVariable("id") @NotBlank(message = "sss") Long id) { return taskService.passTask(id); }
- 接下来就是要进行全局异常错误信息捕捉
使用SpringBoot自带的ControllerAdvice,可以把系统内部的异常统一处理。用起来也很简单。
/** * @Author Tzeao * @create 2022/1/4 0004 23:42 * 全局异常处理类 */ @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { /** * 数据校验异常 */ @ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class}) public Result handleValidatedException(Exception e) { Result resp = null; //参数校验有问题时可以在这输出问题 //System.out.println(e); if (e instanceof MethodArgumentNotValidException) { // BeanValidation exception MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e; resp = Result.fail(HttpStatus.BAD_REQUEST.value(), ex.getBindingResult().getAllErrors().stream() .map(ObjectError::getDefaultMessage) .collect(Collectors.joining("; ")) ); } else if (e instanceof ConstraintViolationException) { // BeanValidation GET simple param ConstraintViolationException ex = (ConstraintViolationException) e; resp = Result.fail(HttpStatus.BAD_REQUEST.value(), ex.getConstraintViolations().stream() .map(ConstraintViolation::getMessage) .collect(Collectors.joining("; ")) ); } else if (e instanceof BindException) { // BeanValidation GET object param BindException ex = (BindException) e; resp = Result.fail(HttpStatus.BAD_REQUEST.value(), ex.getAllErrors().stream() .map(ObjectError::getDefaultMessage) .collect(Collectors.joining("; ")) ); } return resp; } }
如果捕捉到异常就会把异常信息(就是message的消息)返回给前端,所以我们会自己封装一个结果类,用于接收成功/失败的结果
/** * @Author Tzeao * @create 2021/12/24 0024 13:07 * 返回的 json格式的结果 */ @Data @AllArgsConstructor public class Result { private boolean success; private int code; private String msg; private Object data; /** * 遍历把数据传出去 * * @param data 结果 * @return 返回成功的结果json */ public static Result success(Object data) { return new Result(true, 200, "success", data); } /** * 失败 * * @param code 状态码 * @param msg 提示消息 * @return 返回失败的消息 */ public static Result fail(int code, String msg) { return new Result(false, code, msg, ""); } }
这样完成了我们需要的数据校验了
2、注意
如果参数的类型是数字类型就使@NotNull
如果参数的类型是字符串就使用@NotBlank
其他就可以使用_NotEmpty_
这样就可以避免一些错误的发生
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律