ConstraintValidator - 用于缺失数据

ConstraintValidator - Use for Missing Data

我有一个调用网络服务的客户端代码来获取日期范围内的每月价格,然后 returns 平均年价格:

@Service
@RequiredArgsConstructor
@Slf4j
public class PriceAverageService {

    private final PriceServiceClient priceServiceClient ;

    public BigDecimal getAverageAnnualPrice(Long productId, LocalDate startDate, LocalDate endDate) {
       
              List<Price> prices = priceServiceClient.getMonthlyPrices(productId, startDate, endDate);

              // code to compute average annual price

             return averageMonthlyPrice;
    }
}

@FeignClient(name="price-service")
@Validated
public interface PriceServiceClient {

    @GetMapping("/product/price")
    @Valid
    @ConsecutivePrices
    List<Price> getMonthlyPrices(
            @RequestParam(name="productId")
            Long productId,
            @RequestParam(name="startDate")
            @DateTimeFormat(iso=DateTimeFormat.ISO.DATE)
            LocalDate startDate,
            @RequestParam(name="endDate")
            @DateTimeFormat(iso=DateTimeFormat.ISO.DATE)
            LocalDate endDate);
    
}

Price class:

@Value
public class Price {

   BigDecimal price;
   LocalDate priceDate;

}

如果在相邻月份没有遗漏价格的月份遗漏价格,则为错误。例如,以下价格数据是错误的:$15.00 Jan 2020, $20.00 Mar 2020。那是因为缺少 Feb 2020。 @ConsecutivePrices 是检查此条件的 ConstraintValidator

我还需要检查 startDateendDate 是否有价格。如果缺少任何一个,则不是错误。如果缺少任何一个,代码应该 return null for getAverageAnnualPrice(而不是计算平均年价格)。

是否应该使用 ConstraintValidator 来检查 startDateendDate 价格是否存在?如果是这样,我会在 getAverageAnnualPrice 中捕获 MethodArgumentNotValidException 吗?

我不会使用 ConstraintValidator 来实现您服务的部分域逻辑。正如您所说,缺少 start/end 日期价格不是错误,而是您的服务应妥善处理的预期情况。 (通常,我会尽量避免在 normal/happy 情况下使用异常。这包括使用 ConstraintValidators。)

相比之下,丢失的连续价格在您的域模型中没有意义(根据您的解释),即调用的服务永远不会 return 除非确实发生了意外情况(例如损坏的数据模型) ).因此,在这种情况下,验证器(并抛出异常)可能是合适的。如果不满足该条件(即,如果有时缺少连续价格 returned 是正常的,例如因为产品暂时停售或类似情况),那么我会重新考虑使用ConstraintValidator 即使在那种情况下也是如此。

(免责声明:我不是 Spring 用户,作为 Java 用户,我从未在客户端界面中使用过约束验证器,所以我可能会遗漏一些东西。但是我认为这些注意事项相当笼统。)