代码之家  ›  专栏  ›  技术社区  ›  Basil Bourque

Bean验证,检查几个整数值之一

  •  0
  • Basil Bourque  · 技术社区  · 3 年前

    使用 Jakarta Bean Validation 版本2或3,我如何检查 int Integer 成员字段有一组有限的值吗?

    对于一个人为的过于简化的例子,考虑一下 record 代表一个桶,其容量应为50或55。

    record Barrel ( 
        UUID id , 
        int capacity   // Constrain to a value of either 50 or 55. 
    ) {}
    

    我该怎么注释呢 capacity 字段,以确保它只有 50 55 作为其数值?

    如果 容量 字段类型为 String ,我可以用 @Pattern 使用正则表达式。

    public record Barrel(
        @NotNull 
        UUID id , 
        @NotNull 
        @Pattern ( regexp = "50|55" )  // Constrain to a value of either "50" or "55". 
        String capacity
    ) {}
    

    运行它。

    package work.basil.example.beanval;
    
    import jakarta.validation.ConstraintViolation;
    import jakarta.validation.Validation;
    import jakarta.validation.Validator;
    import jakarta.validation.ValidatorFactory;
    
    import java.util.Set;
    import java.util.UUID;
    
    public class App
    {
        public static void main ( String[] args )
        {
            App app = new App();
            app.demo();
        }
    
        private void demo ( )
        {
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            Validator validator = factory.getValidator();
    
            Barrel barrel = new Barrel( UUID.fromString( "e78456ac-6f12-45ae-b8e1-c3b8193a920e" ) , "55" );
            Set < ConstraintViolation < Barrel > > violations = validator.validate( barrel );
            System.out.format( "INFO - Found %d violations.\n" , violations.size() );
            violations.forEach( barrelConstraintViolation -> System.out.println( barrelConstraintViolation.getMessage() ) );
        }
    }
    

    我怎样才能得到同样的效果 int / 整数 至于a 字符串 ?

    0 回复  |  直到 3 年前
        1
  •  3
  •   Nikos Paraskevopoulos    3 年前

    我认为没有内置的验证器。然而,构建自己的东西是微不足道的:

    1. 添加约束注释:

       import static java.lang.annotation.ElementType.FIELD;
       import static java.lang.annotation.ElementType.PARAMETER;
       import static java.lang.annotation.RetentionPolicy.RUNTIME;
      
       import javax.validation.Constraint;
       import javax.validation.Payload;
       import java.lang.annotation.Retention;
       import java.lang.annotation.Target;
      
       @Target({FIELD,PARAMETER})
       @Retention(RUNTIME)
       @Constraint(validatedBy = OneOfValidator.class)
       public @interface OneOf {
      
           String message() default "...provide your default message here...";
      
           Class<?>[] groups() default { };
      
           Class<? extends Payload>[] payload() default { };
      
           /** The array of allowed values. */
           int[] value();
       }
      

      请注意,它引用了实际的验证器类(见下文),您必须提供适当的验证消息。

    2. 创建验证器逻辑:

       import static java.util.stream.Collectors.toSet;
      
       import javax.validation.ConstraintValidator;
       import javax.validation.ConstraintValidatorContext;
       import java.util.Arrays;
       import java.util.Set;
      
       public class OneOfValidator implements ConstraintValidator<OneOf, Integer> {
      
           private Set<Integer> allowedValues;
      
           @Override
           public void initialize(OneOf constraintAnnotation) {
               allowedValues = Arrays.stream(constraintAnnotation.value()).boxed().collect(toSet());
           }
      
           @Override
           public boolean isValid(Integer i, ConstraintValidatorContext constraintValidatorContext) {
               return i == null || allowedValues.contains(i);
           }
       }
      
    3. 用途:

       @OneOf({50,55})
       int capacity;
      

    注意:对于像你这样的用例,可以 enum 更合适吗?