2

我有以下 POJO:

import java.util.Optional;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import org.immutables.value.Value;

@Value.Immutable
public interface ABC {
    Optional<@NotBlank String> test();

    Optional<@Size(max = 280) String> testSize();
}

我正在使用 javax 验证来验证 ABC 类的对象,如下所示:

public static Set<TestConstraintViolation> validateInternalTest(final Object type, final Class<?>... groups) {
        Set<TestConstraintViolation> violations = new HashSet<>();
        for (Method method : type.getClass().getInterfaces()[0].getDeclaredMethods()) {
            try {
                VALIDATOR.validateReturnValue(
                        type,
                        method,
                        method.invoke(type),
                        groups).forEach(constraint -> {
                    TestConstraintViolation testConstraintViolation = new TestConstraintViolation(
                            method.getName(),
                            constraint.getMessageTemplate()
                    );
                    violations.add(testConstraintViolation);
                });
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new IllegalStateException("", e);
            }
        }
        return violations;
    }

现在,当我尝试使用 ABC 的这个验证器函数对象进行验证时,我看到了一个奇怪的问题:

@Test
public void test() {
    ABC abc = ABCType.builder().build();
    assertThat(validateInternalTest(abc))
            .hasViolation("test", "{javax.validation.constraints.NotBlank.message}");

    ABC abc2 = ABCType.builder().test("test").build();
    assertThat(validateInternalTest(abc2))
            .hasNoViolations();
}

使用 abc 对象,如果未通过测试,即使它是可选的,但未通过 testSize 工作正常,它也会返回违规。

据我说,使用 Optional,它们都应该工作。不是吗?

Immutables 或 javax 验证是否存在问题?请帮忙。

4

2 回答 2

1

什么是可选类型? Optional 是包装单个值的新容器类型(如果该值可用)。因此,它旨在传达该值可能不存在的含义。以这种方法为例:

如果您使用 Optional,这意味着价值可能不存在,并且将 @NotBlank 与 Optional 结合使用对我来说似乎不是一个明智的主意。

于 2019-09-23T04:57:23.073 回答
1
  • JSR 380规范 (Bean Validation 2.0) 将空选项 ( )Optional.empty()视为null.

  • 大多数约束(包括@Size)不认为null是违反约束的,这就是空的可选(视为null)通过验证的原因。这也是经常遇到的原因@NotNull @Size(min = 1, max = 2) String x;(即同时检查 size 和 notnull)。

  • 然而,@NotBlank约束是不允许nulls 的例外之一(认为它们是违规)。这就是为什么@NotBlank在大多数其他人不会失败的地方失败的原因。

此处提出了一个类似的问题作为 Hibernate Validator 问题。请参阅问题中的第一个回复(由 Guillaume Smet 撰写):

这是我们在编写 Bean Validation 2.0 规范时做出的选择。我们将空 Optional 的值视为 null。

大多数约束都不关心,因为它们不会因为 null 而失败,但实际上对于@NotBlank,我们认为 null 是无效值。

于 2020-01-25T15:32:43.520 回答