代码之家  ›  专栏  ›  技术社区  ›  Eugene Mamaev

用于列表验证的自定义ConstraintValidator

  •  1
  • Eugene Mamaev  · 技术社区  · 6 年前

    使用spring boot 2.0.3.release、javax.validation 2.0.1.final。

    我需要验证进入控制器的请求:

    @RestController
    @CrossOrigin
    @RequestMapping("/quotas/")
    @AllArgsConstructor
    @Slf4j
    public class QuotasController {
    
        private QuotasService quotasService;
    
        @ApiOperation("Post quotas")
        @PostMapping(value = "/quotas", produces = MediaType.APPLICATION_JSON_VALUE)
        public void quotas(@Valid @RequestBody List<Quota> quotaList){
            quotasService.insertQuotas(quotaList);
        }
    }
    

    调用服务:

    @AllArgsConstructor
    @Service
    @Slf4j
    public class QuotasService {
        private QuotasRepository quotasRepository;
    
        public void insertQuotas(List<Quota> quotaList) {
            quotasRepository.saveAll(quotaList);
        }
    }
    

    将对象保存到MongoRepository方法中 <S extends T> List<S> saveAll(Iterable<S> var1) .

    我还有一个自定义注释:

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = 
    SumOfValuesEqualsToOneHundredValidator.class)
    public @interface SumOfValuesEqualsToOneHundred {
        String message() default "Sum of fields doesn't equal to 100";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    

    验证人:

    public class SumOfValuesEqualsToOneHundredValidator implements 
    ConstraintValidator<SumOfValuesEqualsToOneHundred, List<QuotaPayment>> 
    {
        @Override
        public void initialize(SumOfValuesEqualsToOneHundred sumOfValuesEqualsToOneHundred) {
            //nothing to do
        }
    
        @Override
        public boolean isValid(List<QuotaPayment> quotaPaymentList, 
        ConstraintValidatorContext context) {
             return quotaPaymentList
                    .stream()
                    .mapToDouble(QuotaPayment::getValue)
                    .sum() == 100;
        }
    }
    

    我的目标是验证DTO:

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Quota {
        @Id
        private Integer storeId;
        @JsonProperty("quotas")
        private List<QuotaDelivery> quotaDeliveryList;
    }
    

    特别是在里面的引用传递对象:

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class QuotaDelivery {
        QuotaDeliveryTypeEnum type;
        @JsonProperty("quotasForPaymentTypes")
        @SumOfValuesEqualsToOneHundred
        List<QuotaPayment> quotaPaymentList;
    }
    

    反对 QuotaPayments value S到100。

    换言之,只有那些 Quota 对象有效,其值来自 QuotaDelivery QuotaPayment 总共100分。

    这个问题已经解决了 SumOfValuesEqualsToOneHundredValidator 被忽略。我的意思是调试模式显示控件从不执行 public boolean isValid(List<QuotaPayment> quotaPaymentList, ConstraintValidatorContext context) 方法。

    我错过了什么?

    感谢您的帮助。

    1 回复  |  直到 6 年前
        1
  •  1
  •   GolamMazid Sajib    6 年前

    使用@valid inside list和@validated in controller类:

    @RestController
    @CrossOrigin
    @RequestMapping("/quotas/")
    @AllArgsConstructor
    @Slf4j
    @Validated
    public class QuotasController {
    
    private QuotasService quotasService;
    
    @ApiOperation("Post quotas")
    @PostMapping(value = "/quotas", produces = MediaType.APPLICATION_JSON_VALUE)
    public void quotas(@Valid @RequestBody List<Quota> quotaList){
        quotasService.insertQuotas(quotaList);
    }
    

    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Quota {
        @Id
        private Integer storeId;
        @JsonProperty("quotas")
        private List< @Valid QuotaDelivery> quotaDeliveryList;
    }
    
    List< @Valid QuotaPayment> quotaPaymentList;