在日常开发中常常会出现接口参数中有开始时间和结束时间两个属性,需要校验两个时间的大小关系,但JSR-303并未给出这样的注解,但是给出了ConstraintValidator这个接口,提供用户的自定义校验。下面开始开始时间和结束时间校验的注解。
1 时间校验注解
这个注解只能应用于类上,通过startTime和endTime方法指定被注解的类的开始时间和结束时间的属性名。
@Target({ElementType.TYPE})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {TimeValidate.class})
public @interface TimeValidate {
String message() default "开始时间不能大于结束时间";
String startTime() default "startTime";
String endTime() default "endTime";
boolean required() default true;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
2 时间校验的实现类TimeValidate
@Slf4j
public class TimeLimitValidate implements ConstraintValidator<TimeLimit, Object> {
private TimeLimit timeLimit;
@Override
public void initialize(TimeLimit constraintAnnotation) {
this.timeLimit = constraintAnnotation;
}
@Override
public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
Object startTime = getObjectPropertyValue(object, timeLimit.startTime());
Object endTime = getObjectPropertyValue(object, timeLimit.endTime());
if(null == startTime || null == endTime || !startTime.getClass().equals(endTime.getClass())) {
return true;
}
if(startTime instanceof Long && (Long)startTime > (Long) endTime) {
return false;
}
if(startTime instanceof Date && ((Date) startTime).getTime() > ((Date)endTime).getTime()) {
return false;
}
return true;
}
/**
* 从Object中获取指定的属性的值
* @param object
* @param paramName
* @return
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
private Object getObjectPropertyValue (Object object, String paramName) {
Field field = null;
try {
field = object.getClass().getDeclaredField(paramName);
field.setAccessible(true);
return field.get(object);
} catch (Exception e) {
log.info("===异常信息 e = ", e);
}
return null;
}
}
通过反射获取类中指定的属性值,在Spring中提供了BeanWrapper接口,可以获取到Object的指定属性的值。这里可以进一步优化。