自定义ConstraintValidator用于列表验证

时间:2018-07-20 12:16:38

标签: validation spring-boot

使用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;
}

内部特别是QuotaDelivery对象:

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

使QuotaPayments'value s与100之和相等。

换句话说,只有那些Quota个对象有效,其QuotaDeliveryQuotaPayment中的值总计为100。

前面提到的问题SumOfValuesEqualsToOneHundredValidator被忽略。我的意思是调试模式表明控件从不执行public boolean isValid(List<QuotaPayment> quotaPaymentList, ConstraintValidatorContext context)方法。

我想念什么?

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

在列表中使用@Valid并在控制器类中使用@Validated:

@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;