【问题标题】:Using Spring @Value inside @Size在@Size 中使用Spring @Value
【发布时间】:2015-07-06 15:58:56
【问题描述】:

我正在使用 Spring Boot 和 javax 验证,尤其是 @Size。 我正在尝试从 application.properties 文件中获取大小约束的值:

@Size(min= @Value("${device.name.minsize}"), max=@Value("${device.name.maxsize}"))
private String name;

但我收到以下编译时错误:

错误:(26, 16) java: 注解对于 int 类型的元素无效

为了解决这个问题,我正在尝试以下方法:

@Size(min=Integer.parseInt( @Value("${device.name.minsize}") ), max=Integer.parseInt( @Value("${device.name.maxsize}") ) )

但这也有多个错误。

如何正确转换@Value 注释? 我走错路了吗? 我正在寻找一种干净的方法来从代码中提取大小限制并进入我可以访问服务器端和模板化 angularJS/html 的配置中。

【问题讨论】:

    标签: java spring validation spring-boot


    【解决方案1】:

    我认为你无法做到这一点。注释需要常量值作为参数,因为它们需要在编译时处理。

    您可以将 xml 外部化: http://beanvalidation.org/1.1/spec/#xml-config

    或者,如果你只想在 AngularJS 中使用 JSR-303 注释元数据,你可以看看 Valdr 和 Valdr BeanValidation: https://github.com/netceteragroup/valdr https://github.com/netceteragroup/valdr-bean-validation

    【讨论】:

    • 两个链接都有帮助,但不是我需要的解决方案。我真的在寻找一种方法来将我的验证的“神奇数字”提取到位,可以从前端和后端访问。对于前端,我什至可以使用模板文件并注入魔法值。
    • 继续并将其标记为正确,因为“不,你不能那样做”的基本答案是正确的。
    【解决方案2】:

    要了解另一种方法,请查看https://github.com/jirutka/validator-spring。 它允许您在 bean 验证注释中使用 SpSEL 表达式,包括配置属性。 但是,您将无法使用像 @Size 这样的标准注释,您必须将约束表述为 SpEL 表达式。

    【讨论】:

      【解决方案3】:

      坏消息:无法使用 Java Validation API 的标准注释来做你想做的事。

      好消息:您可以轻松创建完全符合您要求的自定义注释。

      您需要创建一个自定义验证注释(我们称之为@ConfigurableSize),它将两个字符串作为参数,一个用于保存最小大小的属性名称,另一个用于保存最大大小的属性名称。

      @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
      @Retention(RUNTIME)
      @Repeatable(ConfigurableSize.List.class)
      @Constraint(validatedBy = {ConfigurableSizeCharSequenceValidator.class})
      public @interface ConfigurableSize {
      
          String message() default "size is not valid";
      
          Class<?>[] groups() default {};
      
          Class<? extends Payload>[] payload() default {};
      
          String minProperty() default "";
      
          String maxProperty() default "";
      
          @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
          @Retention(RUNTIME)
          @Documented
          @interface List {
              ConfigurableSize[] value();
          }
      
      }
      

      验证器将在初始化时检索属性值,然后它将执行与@Size 约束完全相同的验证检查。即使违反约束也会有完全相同的消息。请注意,如果省略属性名称,minmax 将分别默认为 0Integer.MAX_VALUE,即 @Size 的默认值相同。

      public class ConfigurableSizeCharSequenceValidator implements ConstraintValidator<ConfigurableSize, CharSequence> {
      
          private final PropertyResolver propertyResolver;
          private int min;
          private int max;
      
          @Autowired
          public ConfigurableSizeCharSequenceValidator(PropertyResolver propertyResolver) {
              this.propertyResolver = propertyResolver;
          }
      
          @Override
          public void initialize(ConfigurableSize configurableSize) {
              String minProperty = configurableSize.minProperty();
              String maxProperty = configurableSize.maxProperty();
              this.min = "".equals(minProperty) ? 0 :
                      propertyResolver.getRequiredProperty(minProperty, Integer.class);
              this.max = "".equals(maxProperty) ? Integer.MAX_VALUE :
                      propertyResolver.getRequiredProperty(maxProperty, Integer.class);
              validateParameters();
          }
      
          private void validateParameters() {
              if (this.min < 0) {
                  throw new IllegalArgumentException("The min parameter cannot be negative.");
              } else if (this.max < 0) {
                  throw new IllegalArgumentException("The max parameter cannot be negative.");
              } else if (this.max < this.min) {
                  throw new IllegalArgumentException("The length cannot be negative.");
              }
          }
      
          @Override
          public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
              if (value == null) {
                  return true;
              } else {
                  int length = value.length();
                  boolean retVal = length >= this.min && length <= this.max;
                  if (!retVal) {
                      HibernateConstraintValidatorContext hibernateContext =
                              context.unwrap(HibernateConstraintValidatorContext.class);
                      hibernateContext.addMessageParameter("min", this.min)
                              .addMessageParameter("max", this.max);
                      hibernateContext.disableDefaultConstraintViolation();
                      hibernateContext
                              .buildConstraintViolationWithTemplate("{javax.validation.constraints.Size.message}")
                              .addConstraintViolation();
                  }
                  return retVal;
              }
          }
      
      }
      

      您在 bean 中应用自定义注解

      public class Device {
      
          @ConfigurableSize(minProperty = "device.name.minsize", maxProperty = "device.name.maxsize")
          private String name;
      
      }
      

      最后在application.properties 中定义属性

      device.name.minsize=4
      device.name.maxsize=8
      

      就是这样。您可以在此博客文章中找到更多详细信息和完整示例: https://codemadeclear.com/index.php/2021/03/22/easily-configure-validators-via-properties-in-a-spring-boot-project/

      【讨论】:

        猜你喜欢
        • 2019-05-14
        • 2013-05-26
        • 2011-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-26
        • 1970-01-01
        相关资源
        最近更新 更多