具有层次结构的 JSR 303 验证
JSR 303 validation with hierarchy
假设我们有一个扩展另一个对象的对象,我想为这两个对象创建自定义验证,例如:Period 和 PeriodAmount 对象。期间是:
public class Period {
private LocalDate startDate;
private LocalDate endDate;
PeriodAmount 是:
public class PeriodAmount extends Period {
private BigDecimal amount;
我有一个针对 Period 的自定义验证器,如下所示:
public class PeriodValidator implements ConstraintValidator<ValidPeriod, Period> {
@Override
public boolean isValid(Period period, ConstraintValidatorContext context) {
LocalDate startDate = period.getStartDate();
LocalDate endDate = period.getEndDate();
if (startDate == null) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("{invalid.start.date.null}").addConstraintViolation();
return false;
}
if (endDate != null && startDate.isAfter(endDate)) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("{invalid.end.date.value}").addConstraintViolation();
return false;
}
return true;
}
}
这非常适合 Period。但是现在我想要一个 PeriodAmount 的自定义验证器,并且我想重用我已经拥有的用于 Period 验证的代码。我该怎么做才能只调用一次验证并验证所有内容:
@ValidPeriodAmount
private PeriodAmount periodAmount;
如果没有自定义验证器,您可以更简单地执行此操作:
public class Period {
@NotNull
private LocalDate startDate;
private LocalDate endDate;
@AssertTrue
public boolean isValid(){
return endDate == null || endDate.isAfter(startDate);
}
}
public class PeriodAmount extends Period{
@AssertTrue
public boolean isValid(){
return super.isValid() && //some other condition
}
}
我找到了解决方案。我不知道这是否是最好的方法,或者是否有更优雅的方法,但它确实有效。这是我拥有的:
public class PeriodAmountValidator implements ConstraintValidator<ValidPeriodAmount, PeriodAmount> {
@Override
public boolean isValid(PeriodAmount periodAmount, ConstraintValidatorContext context) {
PeriodValidator validator = new PeriodValidator();
if (!validator.isValid(periodAmount, context)) {
return false;
}
BigDecimal amount = periodAmount.getAmount();
if (amount == null) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("{invalid.amount.null}").addConstraintViolation();
return false;
}
if (amount.intValue() <= 0) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("{invalid.amount.value}").addConstraintViolation();
return false;
}
return true;
}
}
任何想法都非常欢迎!
假设我们有一个扩展另一个对象的对象,我想为这两个对象创建自定义验证,例如:Period 和 PeriodAmount 对象。期间是:
public class Period {
private LocalDate startDate;
private LocalDate endDate;
PeriodAmount 是:
public class PeriodAmount extends Period {
private BigDecimal amount;
我有一个针对 Period 的自定义验证器,如下所示:
public class PeriodValidator implements ConstraintValidator<ValidPeriod, Period> {
@Override
public boolean isValid(Period period, ConstraintValidatorContext context) {
LocalDate startDate = period.getStartDate();
LocalDate endDate = period.getEndDate();
if (startDate == null) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("{invalid.start.date.null}").addConstraintViolation();
return false;
}
if (endDate != null && startDate.isAfter(endDate)) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("{invalid.end.date.value}").addConstraintViolation();
return false;
}
return true;
}
}
这非常适合 Period。但是现在我想要一个 PeriodAmount 的自定义验证器,并且我想重用我已经拥有的用于 Period 验证的代码。我该怎么做才能只调用一次验证并验证所有内容:
@ValidPeriodAmount
private PeriodAmount periodAmount;
如果没有自定义验证器,您可以更简单地执行此操作:
public class Period {
@NotNull
private LocalDate startDate;
private LocalDate endDate;
@AssertTrue
public boolean isValid(){
return endDate == null || endDate.isAfter(startDate);
}
}
public class PeriodAmount extends Period{
@AssertTrue
public boolean isValid(){
return super.isValid() && //some other condition
}
}
我找到了解决方案。我不知道这是否是最好的方法,或者是否有更优雅的方法,但它确实有效。这是我拥有的:
public class PeriodAmountValidator implements ConstraintValidator<ValidPeriodAmount, PeriodAmount> {
@Override
public boolean isValid(PeriodAmount periodAmount, ConstraintValidatorContext context) {
PeriodValidator validator = new PeriodValidator();
if (!validator.isValid(periodAmount, context)) {
return false;
}
BigDecimal amount = periodAmount.getAmount();
if (amount == null) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("{invalid.amount.null}").addConstraintViolation();
return false;
}
if (amount.intValue() <= 0) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("{invalid.amount.value}").addConstraintViolation();
return false;
}
return true;
}
}
任何想法都非常欢迎!