1. controller层直接使用校验注解校验简单参数。比如@Max等等
类上面打注解 @Validated
参数前面打注解 @Max
@Api(value = "分类", tags = "分类模块")
@RestController
@RequestMapping("/category")
@Validated
public class CategoryController {
// 举例:id限制最大为10
@ApiOperation(value = "单个查询", notes = "1.0版本")
@GetMapping("/id/{id}")
public CategoryVO getById(@PathVariable @Max(10) Long id) {
return null;
}
}
2. controller层要校验请求对象
要校验的对象前面打注解 @Validated
对象内部打上需要的注解
如果对象内还有对象,则在内部对象字段打注解@Valid,然后内部对象类里的属性打上各种校验注解
@PostMapping("/add")
public Boolean add(@RequestBody @Validated CategoryDTO categoryDTO) {
CategoryDO categoryDO = new CategoryDO();
BeanUtils.copyProperties(categoryDTO, categoryDO);
return categoryService.save(categoryDO);
}
/**
* @author wangningbo
*/
@Getter
@Setter
@ApiModel(value = "CategoryDTO对象", description = "新增或修改对象")
public class CategoryDTO {
@NotBlank
@ApiModelProperty("名称")
private String name;
@URL
@ApiModelProperty("图片")
private String img;
@ApiModelProperty("描述")
private String description;
@ApiModelProperty("父id")
private Long parentId;
@ApiModelProperty("上线:0->下架;1->上线;")
private Boolean online;
@ApiModelProperty("排序")
private Integer sort;
}
3. @Validated 和 @Valid
有一定的相似性,他们都是开启或关闭校验的开关
4. 自定义校验注解
场景举例:假设用户注册账号,要校验它2次输入的密码是否一致,并且密码的长度要在8~16位
自定义校验注解
/**
* 自定义校验注解
* true 密码长度要在8~16位,且两次密码相同
*
* @author wangningbo
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Constraint(validatedBy = PasswordEqualValidator.class)
public @interface PasswordEqual {
int min() default 8;
int max() default 16;
String message() default "passwords are not equal";
Class>[] groups() default {};
Class extends Payload>[] payload() default {};
}
自定义注解的验证器
/**
* passwordEqual 注解的验证器
*
* @author wangningbo
*/
public class PasswordEqualValidator implements ConstraintValidator> {
int min;
int max;
@Override
public void initialize(PasswordEqual constraintAnnotation) {
this.min = constraintAnnotation.min();
this.max = constraintAnnotation.max();
}
@Override
public boolean isValid(Map map, ConstraintValidatorContext constraintValidatorContext) {
String password1 = map.get("password1");
String password2 = map.get("password2");
if (password1.length() < min || password1.length() > max) {
return false;
}
return password1.equals(password2);
}
}
以后在使用的时候,直接把注解打在类上即可
5. 分组校验
分组
/**
* @author wangningbo
*/
public interface AddGroup {
}
/**
* 空接口,用于 JSR303 分组校验
*
* @author wangningbo
*/
public interface UpdateGroup {
}
分组校验分为以下3种情况
5.1 单分组校验
场景举例:我要指定新增新增的时候校验哪些字段
解决思路:新增接口入参的时候指定对象使用的分组,对象内的字段也指定分组
指定对象使用哪个分组进行校验 @Validated({AddGroup.class})
@PostMapping("/add")
public Boolean add(@RequestBody @Validated({AddGroup.class}) CategoryDTO categoryDTO) {
}
注解的groups属性指定在哪个分组的情况下进行校验。没有指定分组的注解在分组校验下不生效。
/**
* @author wangningbo
*/
@Getter
@Setter
@ApiModel(value = "CategoryDTO对象", description = "新增或修改对象")
public class CategoryDTO {
@Null(groups = {AddGroup.class})
@ApiModelProperty("主键id")
private Long id;
@NotBlank(groups = {AddGroup.class})
@ApiModelProperty("名称")
private String name;
@NotBlank(groups = {AddGroup.class})
@URL(groups = {AddGroup.class)
@ApiModelProperty("图片")
private String img;
@ApiModelProperty("描述")
private String description;
@ApiModelProperty("父id")
private Long parentId;
@ApiModelProperty("上线:0->下架;1->上线;")
private Boolean online;
@ApiModelProperty("排序")
private Integer sort;
}
结果:从上面可以看字段id、name、img这三个字段指定了分组校验的AddGroup分组,到进行新增的时候,就会校验这三个字段
5.2 多分组校验
场景举例:img字段,新增的时候必须填写,且必须为url。修改的时候可以不填写,但是填写了就必须为url。
解决思路:新增接口入参的时候指定对象使用的分组,新增和修改都要对img这个字段有一定的限制,根据不同的场景限制不同的分组即可
指定对象使用哪个分组进行校验 @Validated({UpdateGroup.class})
@PostMapping("/update")
public Boolean update(@RequestBody @Validated({UpdateGroup.class}) CategoryDTO categoryDTO) {
}
注解的groups属性指定在哪个分组的情况下进行校验。没有指定分组的注解在分组校验下不生效。
@Getter
@Setter
@ApiModel(value = "CategoryDTO对象", description = "新增或修改对象")
public class CategoryDTO {
@NotNull(groups = {UpdateGroup.class})
@Null(groups = {AddGroup.class})
@ApiModelProperty("主键id")
private Long id;
@NotBlank(groups = {AddGroup.class})
@ApiModelProperty("名称")
private String name;
@NotBlank(groups = {AddGroup.class})
@URL(groups = {AddGroup.class, UpdateGroup.class})
@ApiModelProperty("图片")
private String img;
@ApiModelProperty("描述")
private String description;
@ApiModelProperty("父id")
private Long parentId;
@ApiModelProperty("上线:0->下架;1->上线;")
private Boolean online;
@ApiModelProperty("排序")
private Integer sort;
}
结果:从上面可以看出字段id和字段img上有的注解指定了update分组。在修改的时候,id必传递,img可以不传,但是如果传了就必须为url格式。否则就会报参数异常错
5.3 不指定分组校验
场景举例:@Validated 注解在controller没有指定校验对象的分组
@PostMapping("/add")
public Boolean add(@RequestBody @Validated CategoryDTO categoryDTO) {
}
/**
* @author wangningbo
*/
@Getter
@Setter
@ApiModel(value = "CategoryDTO对象", description = "新增或修改对象")
public class CategoryDTO {
@NotNull(groups = {UpdateGroup.class})
@Null(groups = {AddGroup.class})
@ApiModelProperty("主键id")
private Long id;
@NotBlank(groups = {AddGroup.class})
@ApiModelProperty("名称")
private String name;
@NotBlank(groups = {AddGroup.class})
@URL(groups = {AddGroup.class, UpdateGroup.class})
@ApiModelProperty("图片")
private String img;
@ApiModelProperty("描述")
private String description;
@ApiModelProperty("父id")
private Long parentId;
@ApiModelProperty("上线:0->下架;1->上线;")
private Boolean online;
@NotNull
@ApiModelProperty("排序")
private Integer sort;
}
结果:可以看到controller层的@Validated没有指定分组,所以校验的对象的属性上的校验注解没有指定分组的才会生效,所以只会校验sort字段。
6. 常用校验注解
@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 附加的 constraint
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内