Skip to content

VO类字段组合校验

  • 业务场景:用户注册时,如果账号类型是公司,则对其邮箱和单位电话做有效性校验,如果是个人,则不需要

  • 代码实现

    1. 自定义注解,validatedBy指定校验器的class文件

      java
      @Constraint(validatedBy = CompanyInfoValidator.class)
      @Target({ ElementType.TYPE })
      @Retention(RetentionPolicy.RUNTIME)
      public @interface ValidateCompanyInfo {
          String message() default "公司信息存在必填项未填";
          
          Class<?>[] groups() default {};
          
          Class<? extends Payload>[] payload() default {};
      }
    2. 校验器CompanyInfoValidator.class,其中实现ConstraintValidator接口的两个属性<自定义注解,应用自定义注解的类名(如果是广泛的,可以定义成Object,然后通过反射获取属性值)>,校验方法的返回值返回是否通过

      java
      public class CompanyInfoValidator implements ConstraintValidator<ValidateCompanyInfo, RegistrationVO> {
          @Override
          public boolean isValid(RegistrationVO registrationVO, ConstraintValidatorContext constraintValidatorContext) {
              Boolean isValid = true;
      
              if ("ORG".equals(registrationVO.getCompanyType())) {
                  // 校验单位邮编有效性
                  if (StringUtils.isBlank(registrationVO.getPostalCode())) {
                      constraintValidatorContext.buildConstraintViolationWithTemplate("单位邮编格式不正确")
                              .addPropertyNode("postalCode").addConstraintViolation();
                      isValid = false;
                  }
                  // 校验单位电话是否为空
                  if (StringUtils.isBlank(registrationVO.getPhone())) {
                      constraintValidatorContext.buildConstraintViolationWithTemplate("字段 单位电话 需要必填,请填写")
                              .addPropertyNode("phone").addConstraintViolation();
                      isValid = false;
                  }
              }
      
              return isValid;
          }
      }
    3. 在类上应用

      java
      @Data
      @ValidateCompanyInfo
      public class RegistrationVO {
          // 公司类型
          private String companyType;
          // 单位邮编
          private String postalCode;
          // 单位电话
          private String phone;
          
          // ... 
      }

字段枚举值的校验

  • 业务场景:修改用户状态时,只允许修改成正常(NORMAL)和禁用(DISABLE),使用一个自定义注解+校验器实现

  • 代码实现

    1. 自定义注解

      java
      @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
      @Retention(RUNTIME)
      @Documented
      @Constraint(validatedBy = {EnumValueValidator.class})
      public @interface EnumValue {
      
          // 默认错误消息
          String message() default "必须为指定值";
      
          String[] strValues() default {};
      
          // 分组
          Class<?>[] groups() default {};
      
          // 负载
          Class<? extends Payload>[] payload() default {};
      
          // 指定多个时使用
          @Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
          @Retention(RUNTIME)
          @Documented
          @interface List {
              EnumValue[] value();
          }
      }
    2. 校验器

      java
      public class EnumValueValidator implements ConstraintValidator<EnumValue, Object> {
      
          private String[] strValues;
      
          @Override
          public void initialize(EnumValue constraintAnnotation) {
              strValues = constraintAnnotation.strValues();
          }
      
          @Override
          public boolean isValid(Object value, ConstraintValidatorContext context) {
              if (value instanceof String) {
                  for (String s : strValues) {
                      if (s.equals(value)) {
                          return true;
                      }
                  }
              }
              return false;
          }
      }
    3. 在属性上应用

      java
      @Data
      public class ModifyUserReqVO {
          @EnumValue(strValues = {"DISABLE", "NORMAL"}, message = "账号状态只能是启用或禁用")
          private String status;
          
          // ...
      }
    4. 对于值要求是整数,或者要进行分组校验的场景,上述代码没有实现,自行补充即可

MIT版权,未经许可禁止任何形式的转载