【问题标题】:Spring Validation: Requiring an exact length on an optional field春季验证:要求可选字段的确切长度
【发布时间】:2015-04-09 23:12:47
【问题描述】:

在 Spring MVC 中,我尝试使用注释来执行表单输入的验证。我有一些字段是可选的,但是当提供输入时,它必须满足某些条件。例如,我有一个字段可以留空,但填写时,答案必须正好是五个字符。

我尝试过类似的东西

@Size(min=5, max=5)
private String value;

但如果用户不填写该字段,则会给用户一个错误。

如何为可选字段提供一些“规则”?

【问题讨论】:

  • 我认为这需要一个自定义验证器。
  • 嘘。我害怕那个。
  • 我使用的是 Spring Boot 2.3。没有遇到这个问题

标签: java spring validation spring-mvc spring-form


【解决方案1】:
  1. 第一个选项是将 value 设置为 null。

如果你看一下 Hibernate 使用的 SizeValidatorForCharSequence:

/**
 * Check that the length of a character sequence is between min and max.
 *
 * @author Emmanuel Bernard
 * @author Gavin King
 * @author Hardy Ferentschik
 */
public class SizeValidatorForCharSequence implements ConstraintValidator<Size, CharSequence> {

    private static final Log log = LoggerFactory.make();

    private int min;
    private int max;

    public void initialize(Size parameters) {
        min = parameters.min();
        max = parameters.max();
        validateParameters();
    }

    /**
     * Checks the length of the specified character sequence (e.g. string).
     *
     * @param charSequence The character sequence to validate.
     * @param constraintValidatorContext context in which the constraint is evaluated.
     *
     * @return Returns <code>true</code> if the string is <code>null</code> or the length of <code>charSequence</code> between the specified
     *         <code>min</code> and <code>max</code> values (inclusive), <code>false</code> otherwise.
     */
    public boolean isValid(CharSequence charSequence, ConstraintValidatorContext constraintValidatorContext) {
        if ( charSequence == null ) {
            return true;
        }
        int length = charSequence.length();
        return length >= min && length <= max;
    }

    private void validateParameters() {
        if ( min < 0 ) {
            throw log.getMinCannotBeNegativeException();
        }
        if ( max < 0 ) {
            throw log.getMaxCannotBeNegativeException();
        }
        if ( max < min ) {
            throw log.getLengthCannotBeNegativeException();
        }
    }
}

只有当长度不匹配最小、最大约束时,大小才无效,如果值为 null 就可以了。

  1. 另一种选择是创建自己的注释和验证器:

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented
    @Constraint(validatedBy = { StringEmptyOrSizeValidator.class })
    public @interface StringEmptyOrSize {
    
        String message() default "{javax.validation.constraints.Size.message}";
    
        Class<?>[] groups() default { };
    
        Class<? extends Payload>[] payload() default { };
    
        /**
         * @return size the element must be higher or equal to
         */
        int min() default 0;
    
        /**
         * @return size the element must be lower or equal to
         */
        int max() default Integer.MAX_VALUE;
    
        /**
         * Defines several {@link Size} annotations on the same element.
         *
         * @see Size
         */
        @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
        @Retention(RUNTIME)
        @Documented
        @interface List {
    
            Size[] value();
        }
    }
    

带有验证器

public class StringEmptyOrSizeValidator implements ConstraintValidator<Size, CharSequence> {

    ....
    public boolean isValid(CharSequence charSequence, ConstraintValidatorContext constraintValidatorContext) {
        if ( charSequence == null || charSequence.isEmpty()) {
            return true;
        }
        int length = charSequence.length();
        return length >= min && length <= max;
    }

    ....
}

【讨论】:

  • 我假设这是一个如何编写自定义验证注释的示例?
  • 是的。我就是这样做的:) 或者你可以使用 null:)
【解决方案2】:

您可以使用 @Pattern(regexp="") 注释来允许自定义模式。之后,错误可以在您的 i12n 属性文件中显示为 Pattern..value=...

示例:

在 bean“人”中:

Pattern(regexp="^[A-ZÑa-zñÁÉÍÓúáéíóú' -]{3,20}$")
private String names;

在messages.properties中:

Pattern.person.names=Please insert a valid name

【讨论】:

  • 考虑扩大你的答案。
【解决方案3】:

一个更简单的解决方案是在你的类中添加一个方法并像这样添加@AssertTrue 注解:

@AssertTrue
public boolean isValidValue() {
        if(this.value == null || this.value.isEmpty()) {
            return true;
        }
        else {
            return this.value.length() == 5 ? false: true;
        }
    }

有了这个你就不需要这个了:@Size(min=5, max=5)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    相关资源
    最近更新 更多