Spring @Valid 构造函数注释不起作用。验证 Dto 的最佳实践

问题描述 投票:0回答:1

今天我正在寻找一种方法来验证我必须返回到 FE 的 DTO。 我认为使用

@Valid
包中的
jakarta.validation
注释创建构造函数可能是一个好主意,因为文档说它可以在构造函数上使用。 因此,我使用示例 DTO 和
@AllArgsConstructor
上的 Lombok 注释以这种方式创建了我的测试:

@AllArgsConstructor(onConstructor_ = {@Valid})
public class TestValidatedDto {
    @NotNull
    private String value1;
    @NotBlank
    private String value2;
    @Min(2)
    @NotNull
    private Integer number;
}

这是Lombok生成的DTO:

public class TestValidatedDto {
    private @NotNull String value1;
    private @NotBlank String value2;
    private @Min(2L) @NotNull Integer number;

    public @Valid TestValidatedDto(final String value1, final String value2, final Integer number) {
        this.value1 = value1;
        this.value2 = value2;
        this.number = number;
    }
}

正如我所期望的,我在构造函数上有

@Valid
注释。 现在我创建了一个测试,但结果不是我需要的。

@SpringBootTest
@Slf4j
class TestValidationAnnotationApplicationTests {

    @Autowired
    private Validator validator;

    @Test
    void testValidation1(){
        TestValidatedDto testValidatedDto = new TestValidatedDto(null, "     ", 1);
        log.info("Created dto: [{}]",testValidatedDto);
        Set<ConstraintViolation<TestValidatedDto>> violations = validator.validate(testValidatedDto);
        violations.forEach(v -> {
            log.info("VIOLATION: field [{}] - value: [{}] - message: [{}]", v.getPropertyPath(), v.getInvalidValue(), v.getMessage());
        });
    }

}

我不明白为什么构造函数上的

@Valid
不起作用。我知道构造函数不是一种方法,但文档说它可以用于验证构造函数的返回。 有谁知道这个注释的正确工作原理吗?

https://jakarta.ee/specifications/bean-validation/3.0/jakarta-bean-validation-spec-3.0.html

如果这不是正确的方法,有人可以解释一些最佳实践来验证 Dto 您需要以简单的方式返回控制器吗?

java spring spring-boot validation lombok
1个回答
0
投票

我在使用你的测试用例时验证成功,你可以尝试我的用例。

DTO:

@Data
@AllArgsConstructor(onConstructor_ = {@Valid})
public class SimpleDTO {


  @NotNull(message = "corpId is null")
  private String corpId;

  @NotNull(message = "userId is null")
  private String userId;

  @NotNull(message = "deptCode is null")
  private String deptCode;

  @NotBlank
  private String notBlank;

}

测试用例:

 @SpringBootTest(classes = SimpleDemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
 class ValidTest {

    @Test
    void testValid() {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        SimpleDTO allArg = new SimpleDTO(null, null, null, "  ");
        Set<ConstraintViolation<Object>> checkResult = validator.validate(allArg);
        if (!CollectionUtils.isEmpty(checkResult)) {
            List<String> resultMsg =checkResult.stream().map(ConstraintViolation::getMessage).collect(Collectors.toList());
            throw new RuntimeException(JSON.toJSONString(resultMsg));
       }
    }


    @Autowired
    private Validator validator;

    private static final Logger LOG = getLogger(ValidTest.class);

    @Test
    @DisplayName("display injected validator SpringBean")
    void displayInjectValidatorBean(){
        LOG.info(validator.getClass().getName());
        SimpleDTO allArg = new SimpleDTO(null, null, null, "  ");
        Set<ConstraintViolation<Object>> checkResult = validator.validate(allArg);
        if (!CollectionUtils.isEmpty(checkResult)) {
            List<String> resultMsg = checkResult.stream().map(ConstraintViolation::getMessage).collect(Collectors.toList());
            throw new RuntimeException(JSON.toJSONString(resultMsg));
        }
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.