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

Java 303/349开始日期早于结束日期验证,java,validation,bean-validation,Java,Validation,Bean Validation,有没有更好的方法来编写Java验证程序,确保开始日期早于结束日期,而不是以以下方式编写类级ConstraintValidator: // VALIDATOR IMPLEMENTATION public class StartBeforeEndDateValidator implements ConstraintValidator<StartBeforeEndDateValid, Object> { // cannot use LocalDate here.

有没有更好的方法来编写Java验证程序,确保开始日期早于结束日期,而不是以以下方式编写类级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;

        ... 
    }
//验证程序实现
公共类StartBeforeendDataValidator实现ConstraintValidator{
//无法在此处使用LocalDate。。。
私有字符串开始;
私有字符串结束;
@凌驾
public void initialize(最终startBeforeendDataValid注释){
start=annotation.start();
end=annotation.end();
}
@凌驾
公共布尔值有效(最终对象bean、最终约束验证或上下文上下文){
试一试{
最后一个字符串startDateStr=BeanUtils.getProperty(bean,start);
最后一个字符串endDateStr=BeanUtils.getProperty(bean,end);
最终LocalDate startDate=新的LocalDate(startDateStr);
最终LocalDate endDate=新的LocalDate(endDateStr);
return!startDate.isAfter(endDate);
}捕获(最终异常e){
返回false;
}
}
}
//用法
@startBeforeendDataValid(start=“startDate”,end=“endDate”)
@实体
公共类MyBean{
@NotNull
@Type(Type=“org.jadira.usertype.dateandtime.joda.PersistentLocalDate”)
私有LocalDate开始日期;
@Type(Type=“org.jadira.usertype.dateandtime.joda.PersistentLocalDate”)
私有LocalDate-endDate;
... 
}

我真的不喜欢必须使用反射从bean中提取2个日期对象。不幸的是,afaik验证规范没有指定只设置要从bean验证的值的方法。

一种方法是向
MyBean添加一个接口

public interface StartEndDateable {
   public LocalDate getStartDate();
   public LocalDate getEndDate();
}

public class MyBean implements StartEndDatable {
...
然后可以将
ConstraintValidator
上的泛型类型设置为新接口,而不是对象

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);
    }
}
公共类StartBeforeendDataValidator实现ConstraintValidator{
@凌驾
公共void初始化(startBeforeendDataValid注释){
}
@凌驾
公共布尔值有效(StartEndDatable bean、ConstraintValidatorContext上下文){
final LocalDate startDate=bean.getStartDate();
final LocalDate endDate=bean.getEndDate();
return!startDate.isAfter(endDate);
}
}

显然,任何想要用开始和结束日期验证的类都必须实现
startendatable
(这不是我所知道的最好的名称,我相信你可以想出更好的方法)并定义
getStartDate
getEndDate
方法,我曾经考虑过添加一个StartEndValidable接口,但这似乎不是最干净的选择——如果我有很多跨参数验证要做,我最终会实现几十个不同的接口只是为了验证,它们会污染我的bean实际要做的事情的本质。我更希望能够将2个日期传递到isValid方法中,但鉴于当前的规范,我认为这是不可能的。如果我没有收到任何类似的信息,我会接受你的答案作为最佳选择。谢谢。另一种选择是使用一个工厂来创建一个
mybeanstartedvalidatable
,它围绕
MyBean
,这样您就不会触及
MyBean
的实现。这确实意味着您将为每个不同的接口提供许多单独的类,但我认为这是一个很小的代价。就我个人而言,我会使用显式类型而不是使用反射,因为以后的任何重构都会有点麻烦,会破坏您的代码,并且会有点头痛,需要查找和修复。您可以随时为MyBean编写特定的ConstraintValidator。如果您需要StartBeforeEndDateValid,那么这可能是最简单的方法,可以避免反射。如果您需要通用解决方案,则需要使用反射。另一种选择可能是Hibernate Validator specific@ScriptAssert.Hi Hardy,StartBeforeEndDate验证器需要是通用的,因为我们有许多需要它的实体。我真的不想使用@ScriptAssert标记进入JavaScript,因为我已经得到了我更喜欢的每个bean的标记:
@AssertTrue(message=“start must before end”)公共布尔值isDatesValid(){return!startDate.isAfter(endDate);}
我将接受George关于接口的回答,因为我认为这是目前最好的解决方案。谢谢你们两位。