【问题标题】:Validation on enum in spring request在春季请求中验证枚举
【发布时间】:2018-09-04 05:52:01
【问题描述】:

我有一个请求WorkerRequest,其中有一个enum,其中有FULL_TIMEMANAGER 等等。

WorkerRequest 中,如何在此枚举上应用长度验证?

示例:枚举类型不应超过 8 个字符。

FULL_TIME 有效(8 个字符)

PERMANENT 无效(9 个字符)

目前如果我输入javax.validation.constraints.Size

  @Size(min = 0, max = 8, message = "Allowed length for workerType is 8.")
  @Enumerated(EnumType.STRING)
  private WorkerType workerType;

它会抛出一个错误:

HV000030:找不到约束的验证器 'javax.validation.constraints.Size' 验证类型 'com.XX.XX.XX.WorkerType'。 检查“workerType”的配置

【问题讨论】:

  • 创建自己的验证,并检查大小,不是 enum_type,而是 enum_type.name();
  • Currentlyenum_type.name() 对这两个常量的长度相同,均为 9 个字符。而不是重命名常量以匹配所需的长度,它会更好,例如覆盖toString() 并检查其长度或引入专用方法。
  • @LuCio 取决于。一旦它是一个字符串,就很容易过滤掉您不想考虑的下划线和其他字符。
  • @Stultuske 好的。如果您只想在某个位置过滤枚举并且不想在枚举中定义它,那么这就是要走的路。
  • 有可能,在某些地方您不希望进行该验证,或者您希望验证的行为有所不同。枚举本身不应该知道验证。例如,如果你有一个在 MY_ENUM.isValid() 上会返回 false 的枚举......你为什么还要从这个枚举开始呢?

标签: java spring validation spring-boot enums


【解决方案1】:

Difference between @Size, @Length and @Column(length=value)中所述

@Size 是一个 Bean Validation 注解,用于验证 关联的 String 具有一个长度以最小值为界的值 和最大值。

您只能指定在数据库中持久化枚举值所需的最大长度。例如,如果您定义@Column(length = 8) 而不是@Size,您将在您的数据库定义中相应地看到workerType VARCHAR(8)

但是有一个解决方法: 假设你有

 public enum WorkerType {PERMANENT , FULL_TIME, ...}; 
  1. 定义自定义验证注解:

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = EnumSizeLimit.class)
    public @interface EnumSizeLimit {
        String message() default "{com.example.app.EnumSizeLimit.message}";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
        Class<? extends Enum<?>> targetClassType();
    }
    
  2. 实施验证器:

    public class EnumSizeLimitValidator implements ConstraintValidator < EnumSizeLimit , String > {
         private Set < String > allowedValues;
    
         @SuppressWarnings({
             "unchecked",
             "rawtypes"
         })
        @Override
        public void initialize(EnumSizeLimit targetEnum) {
        Class << ? extends Enum > enumSelected = targetEnum.targetClassType();
        allowedValues = (Set < String > ) EnumSet.allOf(enumSelected).stream().map(e - > ((Enum << ? extends Enum << ? >> ) e).name())
            .collect(Collectors.toSet());
        }
    
        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
            return value == null || (value.length>=0 && value.length<=8)) ? true : false;
        }
    }
    
  3. 定义字段:

    @EnumSizeLimit (targetClassType = WorkerType.class, message = "your message" 
    private String workerType; 
    

【讨论】:

    【解决方案2】:

    我认为不需要尺寸验证。在请求中使用枚举的事实将迫使序列化将值映射到枚举可能值之一。如果你用“invalid”作为worker类型填充字符串json,spring会抛出:

    org.springframework.http.converter.HttpMessageNotReadableException:JSON 解析错误:无法从字符串“无效”反序列化 WorkerType 类型的值:值不是声明的枚举实例名称之一:等等。

    您可以在自定义休息异常处理程序中捕获异常

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      相关资源
      最近更新 更多