1. 关于修改注解@FutureOrPresent的校验方法 {#1.-%E5%85%B3%E4%BA%8E%E4%BF%AE%E6%94%B9%E6%B3%A8%E8%A7%A3%40futureorpresent%E7%9A%84%E6%A0%A1%E9%AA%8C%E6%96%B9%E6%B3%95}
1.1 书接上回 {#1.1-%E4%B9%A6%E6%8E%A5%E4%B8%8A%E5%9B%9E}
在上文中通过修改注解@FutureOrPresent的校验方法,实现了请求体中Date类型参数在天这一精度下与当天日期比较的问题。
了解当时的做法可以去看这篇文章。 https://tch.cool/archives/43FGGXSM
1.2 有个问题 {#1.2-%E6%9C%89%E4%B8%AA%E9%97%AE%E9%A2%98}
但是这么做有个问题,注解@FutureOrPresent的校验方法被修改了,如果还有需求要用到原生注解@FutureOrPresent怎么办?
自定义的校验器CustomConstraintValidator和约束验证器工厂类CustomConstraintValidatorFactory对别的注解有没有影响?
毕竟修改了代码就会有风险,现在没有不代表以后没有。
看来还是不够优雅,那就自定义个注解来解决需求吧。
2. 自定义注解@FutureOrPresentDay {#2.-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3%40futureorpresentday}
2.1 新建注解@FutureOrPresentDay {#2.1-%E6%96%B0%E5%BB%BA%E6%B3%A8%E8%A7%A3%40futureorpresentday}
说明一下@Constraint:将此注解标记为一个约束注解,并指定了用于验证该约束的验证器类(CustomConstraintValidator)。
/**
* @author denchouka
* @description 必须是现在或未来的日期(以天为精度)
* @date 2024/12/4 22:52
*/
@Documented
@Constraint(validatedBy = CustomConstraintValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface FutureOrPresentDay {
String message() default "必须是现在或未来的日期(以天为精度)";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
`}`
2.2 自定义校验方法isValid {#2.2-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%A1%E9%AA%8C%E6%96%B9%E6%B3%95isvalid}
/**
* @author denchouka
* @description 注解FutureOrPresent的自定义验证器
* @date 2024/12/1 15:28
*/
public class CustomConstraintValidator implements ConstraintValidator<FutureOrPresentDay, Date> {
@Override
public boolean isValid(Date date, ConstraintValidatorContext context) {
// 指定时区为Asia/Shanghai
ZoneId shanghaiZone = ZoneId.of("Asia/Shanghai");
// 获取当前日期
LocalDate now = LocalDate.now(shanghaiZone);
// 要校验的日期转换为LocalDate
LocalDate compare = date.toInstant().atZone(shanghaiZone).toLocalDate();
// 判断校验的日期是否是今天或以后
return !now.isAfter(compare);
}
`}`
3. 测试一下 {#3.-%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%8B}
@Data
public class DemoDto implements Serializable {
private static final long serialVersionUID = 2251918778365338096L;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@FutureOrPresent(message = "date1必须是以后或现在的时间")
private Date date1;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@FutureOrPresent(message = "date2必须是以后或现在的时间")
private Date date2;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@FutureOrPresent(message = "date3必须是以后或现在的时间")
private Date date3;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@FutureOrPresentDay(message = "date4必须是以后或现在的时间")
private Date date4;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@FutureOrPresentDay(message = "date5必须是以后或现在的时间")
private Date date5;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@FutureOrPresentDay(message = "date6必须是以后或现在的时间")
private Date date6;
`}`
还是之前用过的例子,请求体中有6个Date型数据date1~3使用注解@FutureOrPresent,date4~6使用注解@FutureOrPresentDay。
测试一下,结果是符合预期的。
打完收工。