参数校验注解
@Valid —— Bean Validation定义 |
@Validated —— Spring Validation定义 |
|
分组 |
无分组功能 |
提供分组功能,可在入参验证时,根据不同的分组采用不同的验证机制。 |
嵌套验证 |
用在方法入参上无法单独提供嵌套验证功能。 能够用在成员属性上,提示验证框架进行嵌套验证。 能配合嵌套验证注解@Valid进行嵌套验证。 |
用在方法入参上无法单独提供嵌套验证功能。 不能用在成员属性上,也无法提供框架进行嵌套验证。 能配合嵌套验证注解@Valid进行嵌套验证。 |
可注解位置 |
可以用在方法、构造函数、方法参数和成员属性上(两者是否能用于成员属性上直接影响能否提供嵌套验证的功能) |
可以用在类型、方法和方法参数上。但是不能用在成员属性上 |
嵌套验证使用@Valid,分组校验时使用@Validated,在controller上对单个参数校验时使用@Validated。
一、对象参数校验
用法:哪用哪添加@Valid/@Validated
场景:POST方法,使用@RequestBody接收参数时使用
1.1 普通校验——使用@Valid
一般场景校验参数,使用valid注解就行,步骤如下:
1、添加校验注解:给类中参数添加校验注解,常用注解如下
//JSR 提供的校验注解 @Null 被注释的元素必须为 null @NotNull 被注释的元素必须不为 null @AssertTrue 被注释的元素必须为 true @AssertFalse 被注释的元素必须为 false @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 @Size(max=, min=) 被注释的元素的大小必须在指定的范围内 @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内 @Past 被注释的元素必须是一个过去的日期 @Future 被注释的元素必须是一个将来的日期 @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式 //Hibernate Validator 提供的校验注解(相当于扩展) @NotBlank(message =) 验证字符串非 null,且长度必须大于 0 @Email 被注释的元素必须是电子邮箱地址 @Length(min=,max=) 被注释的字符串的大小必须在指定的范围内 @NotEmpty 被注释的字符串的必须非空 @Range(min=,max=,message=) 被注释的元素必须在合适的范围内
@NotNull 、@NotEmpty、 @NotBlank 3个注解的区别
- @NotNull 适用于任何对象,不能为null (一般用这个,如Integer)
- @NotBlank 适用于String,不为null,并且字符串trim()以后length要大于0(不为“”) (String类型的用这个)
- @NotEmpty 适用于String、Collection、Map或者数组,不能为Null,且长度或元素个数必须大于0(可以为“”)
@Pattern:注解适用于String,对于其他类型会报错:No validator could be found for constraint 'javax.validation.constraints.Pattern' validating type 'java.lang.Integer
2、添加@Valid注解:在需要校验的对象前添加@Valid注解即可
- 1. 校验对静态变量不生效
- 2. 对于校验不通过的处理
- 在使用 @Valid 注解的参数后可以紧跟着一个 BindingResult 类型的参数,用于获取校验结果(将校验结果封装在BingdingResult对象中,不会抛出异常);
- 校验不通过会抛出异常,然后全局异常处理(推荐)
3、处理异常:全局捕获异常,统一处理
@ControllerAdvice public class BaseExceptionHandler { @ResponseBody @ExceptionHandler(MethodArgumentNotValidException.class) public HttpResponse handle(MethodArgumentNotValidException e) { FieldError fieldError = e.getBindingResult().getFieldError(); return HttpResponse.builder().code(500).msg(fieldError.getDefaultMessage()).build(); } } //这里的MethodArgumentNotValidException是在校验时抛出的,实际情上因为校验失败还会抛出其它异常,不过一般都是由于开发过程中导致的问题,与用户的输入无关,所以可以统一响应"系统异常",无需单独处理。
@ExceptionHandler(BindingException.class) //实体对象前不加@RequestBody注解,单个对象内属性校验未通过抛出的异常类型 //spring-context包里面的异常
@ExceptionHandler(ValidationException.class) //实体对象前不加@RequestBody注解,校验方法参数或方法返回值时,未校验通过时抛出的异常 //Validation-api包里面的异常
@ExceptionHandler(MethodArgumentNotValidException.class) //实体对象前加@RequestBody注解,抛出的异常为该类异常 //spring-context包里面的异常
1.2 分组校验——@Validated
1、设置分组接口
package com.datamanager.vo.request; import javax.validation.groups.Default; public class ValidationGroups { public interface Create extends Default { } public interface Update extends Default { } } //分组接口类只是普通的接口类并没有多大意义,只是用来标识这个属性哪种情况下被验证
不会自动验证默认分组:使用分组功能后,对于不指定分组的属性,属于默认分组,但是不会自动验证默认分组。
解决方法:1、所有需要验证的属性都必须添加指定分组 2、如上所示,分组接口继承Default接口
2、添加校验注解:给类中参数添加校验注解
package com.datamanager.vo.request; import lombok.Data; import org.hibernate.validator.constraints.Range; import javax.validation.constraints.*; @Data public class DatasetRequest { //update分组 @NotNull(message = "id不能为空", groups = {ValidationGroups.Update.class}) private Integer id; //create分组 @NotBlank(message = "name不能为空", groups = {ValidationGroups.Create.class}) @Size(max = 32, message = "name超出最大长度", groups = {ValidationGroups.Create.class}) @Pattern(regexp = "^[A-Za-z0-9_-]+$", message = "name由中文、英文、下划线和-组成", groups = {ValidationGroups.Create.class}) private String name; //默认分组 @NotBlank(message = "cnName不能为空") @Size(max = 20, message = "cnName超出最大长度") @Pattern(regexp = "^[\\u4e00-\\u9fa50-9]+$", message = "cn_name由中文和数字组成") private String cnName; }
3、使用Validated注解(在需要校验的对象前添加@Validated注解,并指定分组)
@PutMapping("/update") public ResponseResult update(@Validated(ValidationGroups.Update.class) @RequestBody DatasetRequest request) { if (!authorityService.isAllowWrite(request.getId(), loginUser)) { return ResponseResult.build(ResponseCodeEnum.NO_AUTHORIZATION); } return datasetService.updateDataset(request); }
二、单个参数校验
用法:类上添加@Validated,然后在需要的地方添加对应校验注解
场景:当GET方法,使用@RequestParam接受参数时,针对单个参数分别校验
1、controller类上添加注解@Validated
2、@RequestParam的参数前添加对应校验注解
三、Service中对参数校验
service类上添加注解@Validated
需要校验的参数前加@Valid
参考资料
https://segmentfault.com/a/1190000038401180 (详细)
https://juejin.cn/post/6844904118536912904 (简洁 + 使用范围)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战