【问题标题】:Bean Validation to check for one of a few integer values用于检查几个整数值之一的 Bean Validation
【发布时间】:2021-03-10 04:05:23
【问题描述】:

使用 Jakarta Bean Validation 版本 2 或 3,我如何检查 intInteger 成员字段是否具有一组有限的值?

对于一个人为的过于简化的示例,请考虑这个record 代表一个桶,其容量字段应为 50 或 55。

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

➥ 我将如何注释 capacity 字段以确保它只有 5055 作为其数值?

如果capacity 字段的类型为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/Integer 如何获得与String 相同的效果?

【问题讨论】:

  • 我认为您需要编写自己的@Constraint。这将使您可以将注释参数设为int[]
  • 我赞同上面的评论——你必须自己写,而且它相当简单,imo。我们也有很多这些自定义验证器

标签: java integer bean-validation


【解决方案1】:

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

  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 是否更合适?

【讨论】:

  • 我的问题中的用例是为简单起见而设计的。一个枚举将是合适的。我的实际用例需要比 Enum 所能提供的更大的灵活性。感谢您的回答和示例代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-18
  • 2022-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-14
相关资源
最近更新 更多