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
。
我还需要检查 startDate
和 endDate
是否有价格。如果缺少任何一个,则不是错误。如果缺少任何一个,代码应该 return null for getAverageAnnualPrice
(而不是计算平均年价格)。
是否应该使用 ConstraintValidator
来检查 startDate
和 endDate
价格是否存在?如果是这样,我会在 getAverageAnnualPrice
中捕获 MethodArgumentNotValidException
吗?
我不会使用 ConstraintValidator 来实现您服务的部分域逻辑。正如您所说,缺少 start/end 日期价格不是错误,而是您的服务应妥善处理的预期情况。 (通常,我会尽量避免在 normal/happy 情况下使用异常。这包括使用 ConstraintValidators。)
相比之下,丢失的连续价格在您的域模型中没有意义(根据您的解释),即调用的服务永远不会 return 除非确实发生了意外情况(例如损坏的数据模型) ).因此,在这种情况下,验证器(并抛出异常)可能是合适的。如果不满足该条件(即,如果有时缺少连续价格 returned 是正常的,例如因为产品暂时停售或类似情况),那么我会重新考虑使用ConstraintValidator 即使在那种情况下也是如此。
(免责声明:我不是 Spring 用户,作为 Java 用户,我从未在客户端界面中使用过约束验证器,所以我可能会遗漏一些东西。但是我认为这些注意事项相当笼统。)
我有一个调用网络服务的客户端代码来获取日期范围内的每月价格,然后 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
。
我还需要检查 startDate
和 endDate
是否有价格。如果缺少任何一个,则不是错误。如果缺少任何一个,代码应该 return null for getAverageAnnualPrice
(而不是计算平均年价格)。
是否应该使用 ConstraintValidator
来检查 startDate
和 endDate
价格是否存在?如果是这样,我会在 getAverageAnnualPrice
中捕获 MethodArgumentNotValidException
吗?
我不会使用 ConstraintValidator 来实现您服务的部分域逻辑。正如您所说,缺少 start/end 日期价格不是错误,而是您的服务应妥善处理的预期情况。 (通常,我会尽量避免在 normal/happy 情况下使用异常。这包括使用 ConstraintValidators。)
相比之下,丢失的连续价格在您的域模型中没有意义(根据您的解释),即调用的服务永远不会 return 除非确实发生了意外情况(例如损坏的数据模型) ).因此,在这种情况下,验证器(并抛出异常)可能是合适的。如果不满足该条件(即,如果有时缺少连续价格 returned 是正常的,例如因为产品暂时停售或类似情况),那么我会重新考虑使用ConstraintValidator 即使在那种情况下也是如此。
(免责声明:我不是 Spring 用户,作为 Java 用户,我从未在客户端界面中使用过约束验证器,所以我可能会遗漏一些东西。但是我认为这些注意事项相当笼统。)