公司内部系统有个工作登记模块
以前的需求是工作完成时间不早于当前时间,只需要用自带的 @Past 注解即可
最近运营同学提了个新需求:工作完成时间只可选择 当日-7 天前 的区间,每月 3 号截上月数据后,不可提交上月工作(比如 4 号时只允许最早提交 1 号的工作)
这时 Validation 内置的校验注解就胜任不了这样复杂的日期区间校验了
翻了下文档,Validation 允许用户自定义校验注解,记录下实现过程
- 注解实现
自定义校验注解
package com.xxx.x.backend.validator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = WorkCompletionTimeIntervalValidator.class)
public @interface WorkCompletionTimeInterval {
String message() default "工作完成时间不在合法区间";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
编写校验类
package com.xxx.x.backend.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.time.LocalDate;
import java.time.LocalDateTime;
public class WorkCompletionTimeIntervalValidator implements ConstraintValidator<WorkCompletionTimeInterval, LocalDateTime> {
@Override
public boolean isValid(LocalDateTime localDateTime, ConstraintValidatorContext constraintValidatorContext) {
// 以下为自定义的时间区间校验,工作完成时间只可选择 当日-7天前 的区间,每月3号截上月数据后,不可提交上月工作
LocalDate today = LocalDate.now();
LocalDate localDate = localDateTime.toLocalDate();
int deadline = 3;
int timeThreshold = 7;
int dayOfMonth = today.getDayOfMonth();
LocalDate beforeDay = dayOfMonth > deadline ? (dayOfMonth - timeThreshold > 0 ? today.minusDays(timeThreshold) : today.minusDays(dayOfMonth)) : today.minusDays(timeThreshold);
return localDate.isAfter(beforeDay) && localDate.isBefore(today.plusDays(1));
}
}
- 注解使用
把编写好的自定义校验注解添加到 VO,自定义校验就完成了,本文未提及的其他 Validation API 使用请参考官方文档
package com.xxx.x.backend.vo;
import com.xxx.x.backend.validator.WorkCompletionTimeInterval;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.*;
import java.time.LocalDateTime;
@Data
@Schema(description = "创建工作表单类")
public class CreateWorkVO {
...
@Schema(description = "完成时间")
@NotNull(message = "完成时间不能为空")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@WorkCompletionTimeInterval() // <-这里
private LocalDateTime completionTime;
...
}
- 校验流程解析
使用 Validation API 进行参数效验步骤整个过程如下图所示,用户访问接口,然后进行参数效验 ,如果效验通过,则进入业务逻辑,否则抛出异常,交由全局异常处理器进行处理
图源:kenx
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于