Spring boot 2 rest 验证器在使用组时调用两次

Spring boot 2 rest validator called twice when groups are used

当我在 Rest 控制器的 class 级别启用 @Validated spring 注释时,会生成 2 个验证上下文(每个都有不同的前缀)。 @Validated 注释是必需的,因为我想使用 2 个不同的验证组,但由于有 2 个验证上下文,所有验证都执行两次。我认为所有验证都应该只验证一次:

    @RestController
    @RequestMapping
    @Validated
    public class KidController {
        private final KidService kidService;

        public KidController(KidService kidService) {
            this.kidService = kidService;
        }

        @PostMapping
        @Validated(OnRegistrationRequest.class)
        @ResponseStatus(HttpStatus.CREATED)
        public KidDTO createKidRegistration(@RequestBody @Valid KidDTO kid) {
            return kidService.saveKid(kid);
        }
    }

    public interface KidValidatorGroup {
        interface OnRegistrationRequest extends Default {
        }

        interface OnCheckInPersist extends Default {
        }
    }


    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonPropertyOrder({"id"})
    @JsonInclude(Include.NON_NULL)
    public class KidDTO {
        @NotEmpty
        private String id;
        @NotEmpty
        private String firstName;
        @KidAgeConstraint
        private Integer age;
        @NotEmpty(groups = OnCheckInPersist.class)
        private String roomDocId;
        @Valid
        private Set<AnswerDTO> answers;
        @Valid
        private Set<GuardianDTO> guardians;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @FieldStrictDependentConstraint(principalField = "answer", 
       dependentField = "description")
    @JsonInclude(Include.NON_NULL)
    public class AnswerDTO {
        @QuestionIdConstraint(groups = OnRegistrationRequest.class)
        private String questionId;
    }

我在调试应用程序时找到了 2 个上下文,第二个上下文的方法名称类似于前缀。

在您的代码中,您有一个注解可以触发对方法参数和方法的验证 return 值:

    @PostMapping
    @Validated(OnRegistrationRequest.class) // this one is "@Valid" with a specified group and will be used for return value validation
    @ResponseStatus(HttpStatus.CREATED)
    public KidDTO createKidRegistration(@RequestBody @Valid /* this one is for method parameter */ KidDTO kid) {
        return kidService.saveKid(kid);
    }

查看屏幕截图中的不同路径。一个是 createKidRegistration.kid.firstName,这是一个参数。如果您只需要验证特定组传递的参数,您应该尝试将 @Valid 替换为 @Validated(OnRegistrationRequest.class),并从方法级别完全删除 @Validated