广告:
话费充值优惠公众号: 惠享乐生活服务
前言:
前端传入的时间需要小于当前时间,因此想到了通过自定义注解实现,就无需在代码中写校验逻辑了。
1. 创建LocalDateTimeRange注解
package com.luck.living.validation;import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;/*** @author xhga*/
@Target(value = {ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER,ElementType.TYPE_USE
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = LocalDateTimeRangeValidator.class
)
public @interface LocalDateTimeRange {String message() default "时间范围不正确";String pattern() default "yyyy-MM-dd HH:mm:ss";// 最小值String min() default "";// 最大值String max() default "";// 最小值取当前时间,即:参数需大于当前时间boolean minUseCurrentDate() default false;// 最大值取当前时间,即:参数需小于当前时间boolean maxUseCurrentDate() default false;Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};}
2. 创建校验类
package com.luck.living.validation;import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;/*** @author xhga*/
public class LocalDateTimeRangeValidator implements ConstraintValidator<LocalDateTimeRange, LocalDateTime> {private LocalDateTime minDate;private LocalDateTime maxDate;boolean minUseCurrentDate = false;boolean maxUseCurrentDate = false;private boolean parseFail = false;@Overridepublic void initialize(LocalDateTimeRange constraintAnnotation) {minUseCurrentDate = constraintAnnotation.minUseCurrentDate();maxUseCurrentDate = constraintAnnotation.maxUseCurrentDate();try {if (!constraintAnnotation.min().isEmpty()) {minDate = LocalDateTime.parse(constraintAnnotation.min(), DateTimeFormatter.ofPattern(constraintAnnotation.pattern()));}if (!constraintAnnotation.max().isEmpty()) {maxDate = LocalDateTime.parse(constraintAnnotation.max(), DateTimeFormatter.ofPattern(constraintAnnotation.pattern()));}} catch (Exception e) {parseFail = true;}}@Overridepublic boolean isValid(LocalDateTime value, ConstraintValidatorContext context) {if (minUseCurrentDate) {minDate = LocalDateTime.now();}if (maxUseCurrentDate) {maxDate = LocalDateTime.now();}if (parseFail) {return false;}// 如果value为null,返回true,因为这里只校验日期是否在范围内,不校验是否为nullif (value == null) {return true;}// 如果minDate和maxDate都为null,不进行校验,返回trueif (minDate == null && maxDate == null) {return true;}// 如果minDate不为null,且value小于minDate,返回falseif (minDate != null && value.isBefore(minDate)) {return false;}// 如果maxDate不为null,且value大于maxDate,返回falsereturn maxDate == null || !value.isAfter(maxDate);}
}
3. 使用LocalDateTimeRange注解
// createTimeEnd需小于当前时间
@LocalDateTimeRange(maxUseCurrentDate = true)
private LocalDateTime createTimeEnd;
与其他注解一样@LocalDateTimeRange与@Valid 搭配使用
注意:
遇到一个坑,我之前把当前时间的赋值写在了initialize方法,由于initialize只会在初始化时执行,导致比较当前时间时,只有第一次校验是取得当前时间,后续都是取得第一次的时间。
因此需要将获取当前时间的逻辑放在isValid方法。
// 错误代码
@Overridepublic void initialize(LocalDateTimeRange constraintAnnotation) {try {if (constraintAnnotation.minUseCurrentDate()) {minDate = LocalDateTime.now();} else if (!constraintAnnotation.min().isEmpty()) {minDate = LocalDateTime.parse(constraintAnnotation.min(), DateTimeFormatter.ofPattern(constraintAnnotation.pattern()));}if (constraintAnnotation.maxUseCurrentDate()) {maxDate = LocalDateTime.now();} else if (!constraintAnnotation.max().isEmpty()) {maxDate = LocalDateTime.parse(constraintAnnotation.max(), DateTimeFormatter.ofPattern(constraintAnnotation.pattern()));}} catch (Exception e) {parseFail = true;}}