一、Spring 中,创建定时任务除了使用@Scheduled 注解外,还可以使用 SchedulingConfigurer。既然两者都可以实现定时任务,那有什么不同呢?
@Schedule注解的一个缺点就是其定时时间不能动态更改,它适用于具有固定任务周期的任务,若要修改任务执行周期,只能走“停服务→修改任务执行周期→重启服务”这条路。
而基于 SchedulingConfigurer 接口方式可以做到。SchedulingConfigurer 接口可以实现在@Configuration 类上,同时不要忘了,还需要@EnableScheduling 注解的支持。
二、如何使用
1、创建数据库表
CREATE TABLE `trip_job_lock` (
`job_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '定时任务名称',
`is_lock` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否开启任务 1-开启,0-关闭',
`job_cron` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定时任务执行时间间隔',
`job_desc` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定时任务中午描述',
PRIMARY KEY (`job_name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '定时任务配置表' ROW_FORMAT = Dynamic;
INSERT INTO `trip_job_lock` VALUES ('1', NULL, '0/5 * * * * ?', NULL);
2、SchedulingConfigurer接口
(实现SchedulingConfigurer接口重写configureTasks方法)
package org.springframework.scheduling.annotation;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
@FunctionalInterface
public interface SchedulingConfigurer {
void configureTasks(ScheduledTaskRegistrar var1);
}
ScheduledTaskRegistrar类的几个方法
方法包含定时任务,延时任务,基于 Cron 表达式的任务,以及 Trigger 触发的任务。
3、具体实现
(1)Mapper接口
public interface JobMapper {
@Select("<script>SELECT is_lock FROM trip_job_lock WHERE job_name = #{jobName}</script>")
public String getIsLock(String jobName);
@Select("<script>SELECT job_cron FROM trip_job_lock WHERE job_name = #{jobName}</script>")
public String getCron(String jobName);
}
(2)定时任务实现SchedulingConfigurer接口
@Component
@SuppressWarnings("all")
@Slf4j
@EnableScheduling
@Configuration
public class AirTicketSettlementScheduler implements SchedulingConfigurer {
@Resource
private AirTicketSettlementTaskService airTicketSettlementTaskService;
@Resource
CtripUtil ctripUtil;
@Autowired
SnowFlake snowFlake;
@Autowired
ScheduledByRedisIP scheduledByRedisIP;
@Autowired
LogRecordService logRecordService;
//飞机结算的url
@Value("${FlightSettlementURL}")
private String FlightSettlementURL;
@Resource
JobMapper jobMapper;
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
//1.添加任务内容(Runnable)
() -> //System.out.println("执行定时任务2: " + LocalDateTime.now().toLocalTime()),
isScheduler(),
//2.设置执行周期(Trigger)
triggerContext -> {
//2.1 从数据库获取执行周期
String cron = jobMapper.getCron("AirTicketSettlementScheduler");
//2.2 合法性校验.
if (StringUtils.isEmpty(cron)) {
// Omitted Code ..
}
//2.3 返回执行周期(Date)
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
//判断定时任务是否已关闭
public void isScheduler(){
String isLock = jobMapper.getIsLock("AirTicketSettlementScheduler");
if("1".equals(isLock)) {
updateAirSettlementTask();
}else{
log.info("机票结算数据入库定时任务已关闭!");
}
}
private void updateAirSettlementTask() {
//定时任务需要执行的任务
..............
}
}