之前的项目要实现一个功能,用个定时任务发送短信,只有工作日发送,短信内容是上个工作日的数据。
当时的做法是建一个工作日表,工作的周末和不工作的周一至周五放在表中。定时任务触发发送短信时,查询当天日期是否在表中,在就看是否是工作日,是就通过递归查找上个工作日,然后拼接那天的数据进行发送,否则不发短信。
工作日表
create table weekday
(
id int auto_increment
primary key,
date_time varchar(255) null comment '日期',
status varchar(2) null comment '状态 Y工作日 N非工作日'
)
comment '工作日表,存放不工作的周一至周五、工作的周六日';
Service实现
这里有用到递归,需注意,递归在工作中还是很常用的。
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.functionrealization.async.SmsServiceImpl;
import com.example.functionrealization.no_repeat_submit.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
@Slf4j
public class WeekdayServiceImpl extends ServiceImpl<WeekdayMapper, Weekday> implements WeekdayService {
@Autowired
private WeekdayMapper weekdayMapper;
@Autowired
private SmsServiceImpl smsService;
@Override
public Result<String> sendSms() throws InterruptedException {
Date date = new Date();
// 根据Date获取年-月-日的字符串
String timeWithDate = WeekDayUtil.getDateStr(date);
Weekday weekday = this.queryWeekday(timeWithDate);
boolean isWeekday = WeekDayUtil.isWeekday(date, weekday);
if (!isWeekday) {
log.debug("非工作日,不发短信,当日时间:{}", timeWithDate);
return Result.error("非工作日,不发短信,当日时间:" + timeWithDate);
}
String lastWeekday = this.getLastWeekday(date);
// 异步发送短信
smsService.springAsyncSendSms();
return Result.success("上个工作日短信发送成功!上个工作日时间:" + lastWeekday);
}
private Weekday queryWeekday(String timeWithDate) {
// 往工作日维护表中找这一天
return weekdayMapper.selectWeekday(timeWithDate);
}
public String getLastWeekday(Date date) {
// 上一天
DateTime yesterday = DateUtil.offsetDay(date, -1);
String yesterdayStr = WeekDayUtil.getDateStr(yesterday);
boolean weekday = WeekDayUtil.isWeekday(yesterday, this.queryWeekday(yesterdayStr));
// 是工作日就返回
if (weekday) {
return yesterdayStr;
}
// 否则递归找上个工作日
return this.getLastWeekday(yesterday);
}
}
工具类
package com.example.functionrealization.get_last_weekday;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import java.util.Date;
public class WeekDayUtil {
/**
* 工作日
*/
public static final String IS_WEEKDAY = "Y";
/**
* 非工作日
*/
public static final String NO_WEEKDAY = "N";
/**
* 是否是工作日
*
* @param date -
* @return true表示工作日
*/
public static boolean isWeekday(Date date, Weekday weekday) {
// 在维护表中,表示可能是上班的周末,不上班的周一至周五
if (ObjectUtil.isNotNull(weekday)) {
//是否工作日 0是 1否
String status = weekday.getStatus();
//工作日
if (WeekDayUtil.IS_WEEKDAY.equals(status)) {
return true;
}
if (WeekDayUtil.NO_WEEKDAY.equals(status)) {
return false;
}
}
// 判断是一周中的星期几,1表示周日,7表示周六
int isSaturday = DateUtil.dayOfWeek(date);
// 非周末,即工作日
return isSaturday != 7 && isSaturday != 1;
}
/**
* 根据Date获取年-月-日的字符串
*
* @param date date
* @return 年-月-日 字符串
*/
public static String getDateStr(Date date) {
DateTime timeStr = DateUtil.parse(date.toString());
return timeStr.toString().substring(0, 10);
}
}
测试
2024-09-15,周日非工作日,不发短信。
2024-09-16,周一非工作日,不发短信。
2024-09-17,周二为中秋节,非工作日,不发短信。
2024-09-18,周三为工作日,发短信,发的是上个工作日也就是放假前(2024-09-14)的数据。
发短信的代码我设置睡眠3秒模拟业务耗时,但是当第一个日志SendSms...打印的时候就返回结果了,是因为使用了异步调用,异步调用后面再出一篇文章讲。
2024-10-08,工作日,发送的是节前9.30的数据。