【總結】spring定時任務
阿新 • • 發佈:2020-11-17
1.spring - @schedule定時任務器
1.1.實現
1.引入依賴
spring3.0後自帶的定時任務器,所以只需引入spring依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
2.定時任務類
@Component public class ScheduleDemo { @Scheduled(cron = "0/2 * * * * ?") public void scheduleMethod(){ System.out.println("定時器被觸發" + new Date()); } }
3.啟動類加@EnableScheduling註解
4.效果.每兩秒列印一次
1.2.cron表示式
1.cron表示式是一個字串,分為6或7個域,每一個域代標一個含義
2.cron有如下兩種語法格式:
(1)秒 分 時 日 月 星期 年
(2)秒 分 時 日 月 星期
推薦使用6個域的表示式(有的定時任務器要求為6個域,否則會出錯)
(注意:星期的1表示星期日)
3.各欄位的含義
(1):表示匹配該域的任意值。假如在Minutes域使用, 即表示每分鐘都會觸發事件。
(2)?:只能用在DayofMonth和DayofWeek兩個域。它也匹配域的任意值,但實際不會。因為DayofMonth和DayofWeek會相互影響。例如想在每月的20日觸發排程,不管20日到底是星期幾,則只能使用如下寫法: 13 13 15 20 * ?, 其中最後一位只能用?,而不能使用,如果使用
(3)-:表示範圍。例如在Minutes域使用5-20,表示從5分到20分鐘每分鐘觸發一次
(4),:表示列出列舉值。例如:在Minutes域使用5,20,則意味著在5和20分每分鐘觸發一次。
(5)#:用於確定每個月第幾個星期幾,只能出現在DayofMonth域。例如在4#2,表示某月的第二個星期三
(6)/:表示起始時間開始觸發,然後每隔固定時間觸發一次。例如在Minutes域使用5/20,則意味著5分鐘觸發一次,而25,45等分別觸發一次
2.spring - SchedulingConfigurer定時任務器
2.1 SchedulingConfigurer介紹
@Schedule註解的一個缺點就是其定時時間不能動態更改,它適用於具有固定任務週期的任務,若要修改任務執行週期,只能走“停服務→修改任務執行週期→重啟服務”這條路。
而基於 SchedulingConfigurer 介面方式可以做到。SchedulingConfigurer 介面可以實現在@Configuration 類上,同時不要忘了,還需要@EnableScheduling 註解的支援
2.2 SchedulingConfigurer實現
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方法
@Component
public class SchedulerTask implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
this.registrar = scheduledTaskRegistrar;
taskTriggerModels = new ArrayList<>();
logger.info("初始化定時任務配置");
//"update OrderTask set IsRunning = 0 where IsExecute = 1 and Isdel = 0"
orderTaskMapper.init();
scheduledTaskRegistrar.addTriggerTask(SyncCompeteAgentInfoByCaChange(), getTrigger(TaskEnum.SyncCompeteAgentInfoByCaChange.getTaskCode()));
//用於controller裡,重新啟動或更新任務
List<TriggerTask> tasks = scheduledTaskRegistrar.getTriggerTaskList();
if (tasks != null && tasks.size() > 0) {
for (TriggerTask task : tasks) {
Optional<TaskTriggerModel> optional = taskTriggerModels.stream().filter(o -> o.getTrigger() == task.getTrigger()).findFirst();
if (optional.isPresent()) {
optional.get().setRunnable(task.getRunnable());
}
}
}
/**
* 從資料庫中獲取觸發時間
*/
private Trigger getTrigger(String taskCode) {
Trigger trigger = new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
OrderTask task = orderTaskMapper.selectByTaskCode(taskCode);
int isContinue = 1;
String[] codeArry = {"2", "3", "6"};
if ("uat".equals(proAction) && !Arrays.asList(codeArry).contains(taskCode)) {
isContinue = 0;
}
if (task != null && isContinue == 1) {
logger.info("任務編碼:" + taskCode + " cron: " + task.getCron());
// 觸發器
CronTrigger trigger = new CronTrigger(task.getCron());
return trigger.nextExecutionTime(triggerContext);
} else {
logger.info("定時任務初始化失敗,任務編碼:{},請檢查資料庫中的任務狀態。", taskCode);
return null;
}
}
};
TaskTriggerModel model = new TaskTriggerModel();
model.setTaskCode(taskCode);
model.setTrigger(trigger);
taskTriggerModels.add(model);
return trigger;
}
}