背景:
\color{purple}{而开始和结束时间如果为同一天那么就只能查询一秒钟的数据,这显然是有问题的 ,}$$\color{purple}{想要查询7.29当天数据我们需要把endDate的时间往后加上一天}
直接解决:
Date beginDate=param.getBeginDate();
Date endDate=param.getEndDate();
if ((beginDate != null && endDate != null) && beginDate.equals(endDate)) {
//如果传入的开始和结束时间一样则结束时间加一天
c.setTime(beginDate);
c.add(Calendar.DAY_OF_MONTH, 1);
Date endTime = c.getTime();
endDateMap.get(arg.getClass()).set(arg, endTime);
}
自定义注解+AOP:
首先项目里要确保引入了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
然后自定义注解,用于标注时间范围查询方法
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeSpanCheck {
//String beginDateFieldName();
//String endDateFieldName();
}
原本想直接手动定义beginDate和endDate字段名,但想了想这样并不好,如果字段改名这里很可能会因为没有一起改而报错, 既然我们都已经使用了注解做标识那不如再使用一次
@Documented
//注意这里的@Target和上面不同,说明该注解用于标注变量
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BeginDate {
}
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EndDate {
}
定义完注解我们把它加到对应的方法和字段上,然后就可以用反射获取了
接下来就可以写aop类了,这里直接上代码+注释
@Component
@Aspect
@Slf4j
public class TimeSpanCheckAop {
private Calendar c = Calendar.getInstance();
//缓存Field避免每次方法调用都做反射的开销
private Map<Class, Field> beginDateMap = new HashMap<>();
private Map<Class, Field> endDateMap = new HashMap<>();
//切点,也就是aop需要执行的地方(在方法实现package中和有@TimeSpanCheck注解的方法)
@Pointcut("execution(* xxx.xxx.service.impl..*(..)) && @annotation(xxx.xxx.service.aop.TimeSpanCheck)")
public void pointCut() {
}
/**
* 如果方法上有@TimeSpanCheck注解且begindate和enddate相同,enddate加一天
*/
@Around("pointCut()")
public Object TimeSpanCheck(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
TimeSpanCheck timeSpanCheck = method.getAnnotation(TimeSpanCheck.class);
if (timeSpanCheck == null) {
return true;
}
Object arg = args[0];
if (beginDateMap.get(arg.getClass()) == null && endDateMap.get(arg.getClass()) == null) {
//遍历入参变量,找到标注了@BeginDate @EndDate的Field并存入缓存map
for (Field field : arg.getClass().getDeclaredFields()) {
BeginDate beginDate = field.getAnnotation(BeginDate.class);
EndDate endDate = field.getAnnotation(EndDate.class);
if (beginDate != null) {
field.setAccessible(true);
beginDateMap.put(arg.getClass(), field);
}
if (endDate != null) {
field.setAccessible(true);
endDateMap.put(arg.getClass(), field);
}
}
}
//获取Field并修改入参
Field beginDateField = beginDateMap.get(arg.getClass());
Field endDateField = endDateMap.get(arg.getClass());
if (beginDateField != null && endDateField != null) {
Date beginDate = (Date) beginDateField.get(arg);
Date endDate = (Date) endDateField.get(arg);
if ((beginDate != null && endDate != null) && beginDate.equals(endDate)) {
//如果传入的开始和结束时间一样则结束时间加一天
c.setTime(beginDate);
c.add(Calendar.DAY_OF_MONTH, 1);
Date endTime = c.getTime();
endDateMap.get(arg.getClass()).set(arg, endTime);
}
}
//原方法执行
return joinPoint.proceed(args);
}
}
验证: