Spring BeanValidation框架的使用总结

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提供者,附加以下注解:

注解名称描述
@Email被注释的元素必须是电子邮箱地址
@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 {};
    

    仅作为使用总结记录,望诸君共勉

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值