Bean Validation 中的 constraint
注解名称 | 描述 |
---|---|
@Null | 被注释的元素必须为 null |
@NotNull | 被注释的元素必须不为 null |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(value) | 被注释的元素必须是一个数字(浮点数),其值必须大于等于指定的最小值 |
@DecimalMax(value) | 被注释的元素必须是一个数字(浮点数),其值必须小于等于指定的最大值 |
@AssertTrue | 被注释的元素必须为 true |
@AssertFalse | 被注释的元素必须为 false |
@Digits (integer, fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 |
@Size(max, min) | 被注释的元素的大小必须在指定的范围内 |
@Future | 被注释的元素必须是一个将来的日期 |
@Past | 被注释的元素必须是一个过去的日期 |
@Pattern(value) | 被注释的元素必须符合指定的正则表达式 |
如果您使用Hibernate Validator作为BeanValidation提供者,附加以下注解:
注解名称 | 描述 |
---|---|
被注释的元素必须是电子邮箱地址 | |
@Length | 被注释的字符串的大小必须在指定的范围内 |
@NotEmpty | 被注释的字符串的必须非空 |
@Range | 被注释的元素必须在给定范围内 |
1.NotNull 和 NotEmpty 和NotBlank 区别
注解名称 | 描述 |
---|---|
@NotEmpty | 用在集合类上面 |
@NotBlank | 用在String上面 |
@NotNull | 用在基本类型上 |
2.字段交叉验证实现方式
业务规则:需要校验密码和确认密码是否相等。
@Equals
注解@AssertTrue
|@AssertFlase
注解public class Bean { private String password; private String confirmPassword; @AssertTrue(message="password must be the same as confirm password") private boolean isValid() { return this.password.equals(this.confirmPassword); }}
3.分组检验
由于业务规则要求,add和update实体的时候,一般都是使用同一个实体类,但是add和update对实体的参数校验不同。
Java Bean Validation提供分组校验的功能,可以实现针对不同的场景应用不同的校验规则。详情请直接去官网查看:hibernate-分组校验
- 定义一个分组接口
public interface AddGroup { }
- bean使用分组接口
public class Person { //添加分组信息:添加的时候不能有id,修改的时候却一定要有id @NotNull(message = "username should not be empty") @validDuplicated(message = "{username.exist}", groups = {AddGroup.class}) private String username; @NotNull(message = "password should not be empty") private String password; }
- 修改controller校验接口
由@Valid
修改成@Validated
添加分组{AddGroup.class
,Default.class
}@PostMapping() public Result<?> create(@Validated({AddGroup.class, Default.class}) @RequestBody Person person) { return new Result<>(person); } @PutMapping() public Result<?> update(@Valid @RequestBody Person person) { return Result.SUCCESS; } ```
- 注意:
1.没有加分组groups的属于Default默认分组。@Validated({Default.class})
表示默认分组,也可以只用@Validated
或者@Valid
表示
2.添加分组groups的属于自定义分组,不属于默认分组。
3.配置分组的时候,记得添加默认分组Default.class
,否则就只会校验groups = {AddGroup.class}
的规则
4.自定义校验规则
由于业务规则,官方提供的原始注解无法满足需求时,需要实现官方提供的@Constraint
注解,来达到自定义校验规则的效果。
-
创建注解,并在其上添加
@Constraint
注解@Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {}) @Documented public @interface ValidDuplicated { String message() default "{valid.duplicated}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
-
实现
ConstraintValidator
接口,并绑定@ValidDuplicated
注解public class PersonValid implements ConstraintValidator<ValidDuplicated, String>{ @Autowired private PersonService personService; @Override public void initialize(ValidDuplicated validDuplicated) { } @Override public boolean isValid(String name, ConstraintValidatorContext context) { if (StringUtils.isBlank(name)) { return false; } return !personService.checkExist(name); } }
-
业务限制
解决方案:
在hibernate 官网中,存在基于 Java 的ServiceLoader 机制的 Hibernate Validator 使用,该机制允许注册额外的约束定义。详情请直接去官网查看:hibernate-额外的约束定义原文介绍:
此ServiceLoader机制还允许解决另一个问题。当您试图向您的最终用户提供相关类并隐藏他们的实现细节时,您可能不想在注释中的
validatedBy()
参数中提及它来公开您的验证器实现。如果您不使用
validatedBy()
参数,您的约束注释将在不知道验证器存在的情况下过自己的生活。Hibernate Validator 也不会知道验证器。这可以通过在类路径中放置一个属性文件来完成。因此,为了确保 Hibernate Validator 自定义校验规则
PersonValid
,您需要创建文件META-INF/services/javax.validation.ConstraintValidator 并将验证器实现的完全限定名称放入其中:com.acme.validation.validators.PersonValid
目录结构为:
-
注意事项
这个自定义校验类实现了ConstraintValidator接口,所以它默认被spring注册为bean对象,所以在其中可用用@Autowiredu或者@Resources注入别的服务。
不用在类上面用@Compent等注解再次注册成spring的bean对象。
自定义验证类型注解类里面必须要加上的属性:
Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {};
仅作为使用总结记录,望诸君共勉