Java 303/349开始日期早于结束日期验证
有没有更好的方法来编写Java验证程序,确保开始日期早于结束日期,而不是以以下方式编写类级ConstraintValidator: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.
// 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关于接口的回答,因为我认为这是目前最好的解决方案。谢谢你们两位。