1. 程式人生 > 實用技巧 >【總結】spring定時任務

【總結】spring定時任務

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;
    }
}