java 自定义注解校验时间段
需求
最近做了一个日历模块, 用户可以在模块中新增日程, 需要录入开始时间(scheduleStartTime)和结束时间(scheduleStartTime). 此时需要校验两个参数的大小关系.
示例代码
1. 自定义注解类
package com.ruoyi.common.annotation;
import com.ruoyi.common.validate.DateValidatorClass;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
/**
* 时间段校验
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//实现类
@Constraint(validatedBy = DateValidatorClass.class)
public @interface TimeInterval {
// 校验未通过时的返回信息
String message() default "开始时间不得大于结束时间";
// 以下两行为固定模板
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
2. 注解的实现类
package com.ruoyi.common.validate;
import com.ruoyi.common.annotation.TimeInterval;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
public class DateValidatorClass implements ConstraintValidator<TimeInterval, Object> {
@Override
public void initialize(TimeInterval constraintAnnotation) {
}
@Override
public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
// 需求:非必填字段(null),不传就不做校验
if (object == null) {
return true;
}
Object startTime = this.getObjectPropertyValue(object, "scheduleStartTime");
Object endTime = this.getObjectPropertyValue(object, "scheduleEndTime");
// 起始创建时间、结束创建时间均有值,则结束创建时间不得小于如起始创建时间
if (null == startTime || null == endTime || !startTime.getClass().equals(endTime.getClass())) {
return true;
}
//long类型对比
if (startTime instanceof Long && endTime instanceof Long) {
return (Long) startTime > (Long) endTime;
}
//LocalDateTime 类型对比
if (startTime instanceof LocalDateTime && endTime instanceof LocalDateTime) {
return ((LocalDateTime) startTime).isBefore((LocalDateTime) endTime);
}
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;
}
}
3. 实体类
package com.ruoyi.web.controller.demo.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.TimeInterval;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@TimeInterval
public class TimeIntervalModel {
/**
* 开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime scheduleStartTime;
/**
* 结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime scheduleEndTime;
public LocalDateTime getScheduleStartTime() {
return scheduleStartTime;
}
public void setScheduleStartTime(LocalDateTime scheduleStartTime) {
this.scheduleStartTime = scheduleStartTime;
}
public LocalDateTime getScheduleEndTime() {
return scheduleEndTime;
}
public void setScheduleEndTime(LocalDateTime scheduleEndTime) {
this.scheduleEndTime = scheduleEndTime;
}
4. 测试 Controller
package com.ruoyi.web.controller.demo.controller;
import com.ruoyi.common.annotation.TimeInterval;
import com.ruoyi.web.controller.demo.domain.TimeIntervalModel;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/demo")
public class DemoController {
@PostMapping("interval")
public String testInteval(@Validated @RequestBody TimeIntervalModel model) {
System.out.println("model. = " + model.getScheduleEndTime());
return "success";
}
}
5. postman测试
{
"msg": "开始时间不得大于结束时间",
"code": 500
}
常见问题及解决方式
1. 请求未进入注解的自定义处理类.
检查controller中方法是否添加 @Validated 注解
2. 注解处理类中获取不到"开始时间"和"结束时间"参数.
检查 添加的参数名 是否和 实体类中的参数名一致.
3. 校验错误.
检查实体类中定义的参数类型, 和处理类中"isValid"是否一致.
例如: private DateTime scheduleStartTime;
那么在 isValid方法中 需要对 DateTime 类型的数据进行处理.