Java 303 / 349 开始日期早于结束日期验证

Java 303 / 349 start date before end date validation

是否有更好的方法来编写 Java 验证器,以确保开始日期在结束日期之前,而不是通过以下方式编写 class 级别的 ConstraintValidator:

// VALIDATOR IMPLEMENTATION

    public class StartBeforeEndDateValidator implements ConstraintValidator<StartBeforeEndDateValid, Object> {

        // cannot use LocalDate here...
        private String start;
        private String end;

        @Override
        public void initialize(final StartBeforeEndDateValid annotation) {
            start = annotation.start();
            end = annotation.end();

        }

        @Override
        public boolean isValid(final Object bean, final ConstraintValidatorContext context) {
            try {
                final String startDateStr = BeanUtils.getProperty(bean, start);
                final String endDateStr = BeanUtils.getProperty(bean, end);

                final LocalDate startDate = new LocalDate(startDateStr);
                final LocalDate endDate = new LocalDate(endDateStr);

                return !startDate.isAfter(endDate);
            } catch (final Exception e) {
                return false;
            }
        }
    }


// USAGE
    @StartBeforeEndDateValid(start = "startDate", end = "endDate")
    @Entity
    public class MyBean {

        @NotNull
        @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
        private LocalDate startDate;

        @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
        private LocalDate endDate;

        ... 
    }

我不太喜欢必须使用反射从 bean 中提取 2 个日期对象这一事实。不幸的是,afaik 验证规范没有指定一种方法来仅设置您想要从 bean 验证的值。

一种方法是向 MyBean

添加一个接口
public interface StartEndDateable {
   public LocalDate getStartDate();
   public LocalDate getEndDate();
}

public class MyBean implements StartEndDatable {
...

然后您可以将 ConstraintValidator 上的通用类型设置为新接口而不是 Object。

public class StartBeforeEndDateValidator implements ConstraintValidator<StartBeforeEndDateValid, StartEndDatable> {

    @Override
    public void initialize(StartBeforeEndDateValid annotation) {
    }

    @Override
    public boolean isValid(StartEndDatable bean, ConstraintValidatorContext context) {
        final LocalDate startDate = bean.getStartDate();
        final LocalDate endDate = bean.getEndDate();

        return !startDate.isAfter(endDate);
    }
}

显然任何 class 然后你想要验证开始和结束日期将必须实施 StartEndDateable (不是我知道的最好的名字,我相信你能想到一些东西更好)并定义 getStartDategetEndDate 方法。