1. 程式人生 > >springboot2 task scheduler 定時任務排程器四種方式

springboot2 task scheduler 定時任務排程器四種方式

使用@EnableScheduling方式

@Component
@Configurable
@EnableScheduling
public class Task1 {
    private static Log logger = LogFactory.getLog(Task1.class);
    @Scheduled(cron = "0/2 * * * * * ")
    public void execute() {
        logger.info("Task1>>" + new Date());
    }
}

xml配置方式

application啟動加入讀取xml

檔案

@SpringBootApplication
@ImportResource(value = { "classpath:applicationContext*.xml" })
public class Springboot2TaskApplication {

	public static void main(String[] args) {
		SpringApplication.run(Springboot2TaskApplication.class, args);
	}
}
<context:component-scan base-package="com.chenyingjun.task.schedual"
>
</context:component-scan> <task:scheduler id="appScheduler" pool-size="2" /> <!-- 調整定時任務 --> <task:scheduled-tasks> <task:scheduled ref="task2" method="method2" cron="0/10 * * * * ?"/> </task:scheduled-tasks>
@Service
public class Task2 {
    private static Log logger =
LogFactory.getLog(Task2.class); public void method2() { logger.info("Task2----method2>>>>" + new Date()); } }

bean建立工廠方法

新建SchedledConfiguration.java檔案

@Configuration
public class SchedledConfiguration {

    /**
     * attention:
     * Details:配置定時任務
     */
    @Bean(name = "jobDetail")
    public MethodInvokingJobDetailFactoryBean detailFactoryBean(Task3 task) {// TestTask為需要執行的任務
        MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
        /*
         *  是否併發執行
         *  例如每5s執行一次任務,但是當前任務還沒有執行完,就已經過了5s了,
         *  如果此處為true,則下一個任務會執行,如果此處為false,則下一個任務會等待上一個任務執行完後,再開始執行
         */
        jobDetail.setConcurrent(false);

        // 設定任務的名字
        jobDetail.setName("jobDetailName");

        // 設定任務的分組,這些屬性都可以儲存在資料庫中,在多工的時候使用
        jobDetail.setGroup("jobDetailGroup");

        /*
         * 為需要執行的實體類對應的物件
         */
        jobDetail.setTargetObject(task);

        /*
         * 通過這幾個配置,告訴JobDetailFactoryBean我們需要執行定時執行ScheduleTask類中的task方法
         */
        jobDetail.setTargetMethod("task");
        return jobDetail;
    }

    /**
     * Details:配置定時任務的觸發器,也就是什麼時候觸發執行定時任務
     */
    @Bean(name = "jobTrigger")
    public CronTriggerFactoryBean cronJobTrigger(JobDetail jobDetail) {
        CronTriggerFactoryBean tigger = new CronTriggerFactoryBean();
        tigger.setJobDetail(jobDetail);
        // 初始時的cron表示式,可以改成從資料庫中獲取
        tigger.setCronExpression("0/2 * * * * ?");
        // trigger的name
        tigger.setName("tiggerName");
        return tigger;

    }

    /**
     * Details:定義quartz排程工廠
     */
    @Bean(name = "scheduler")
    public SchedulerFactoryBean schedulerFactory(Trigger trigger) {
        SchedulerFactoryBean bean = new SchedulerFactoryBean();
        // 用於quartz叢集,QuartzScheduler 啟動時更新己存在的Job
        bean.setOverwriteExistingJobs(true);
        // 延時啟動,應用啟動1秒後
        bean.setStartupDelay(1);
        // 註冊觸發器
        bean.setTriggers(trigger);
        return bean;
    }
}

新建Task任務

@Service
public class Task3 {

    @Resource(name = "jobTrigger")
    private CronTrigger cronTrigger;

    @Resource(name = "scheduler")
    private Scheduler scheduler;

    private static Log logger = LogFactory.getLog(Task3.class);

    public void task() {
        logger.info("Task3---------" + new Date());
    }

    /**
     * 設定cron並重啟定時器
     * @param cron cron值
     */
    public void setCron(String cron) {
        try {
            // 表示式排程構建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
            // 按新的cronExpression表示式重新構建trigger
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());
            trigger = trigger.getTriggerBuilder().withIdentity(cronTrigger.getKey())
                    .withSchedule(scheduleBuilder).build();
            // 按新的trigger重新設定job執行
            scheduler.rescheduleJob(cronTrigger.getKey(), trigger);
        } catch (SchedulerException e) {
            logger.info("cron表示式錯誤");
        }
    }
}

其中setCron方法可以進行重新設定任務排程時間

ThreadPoolTaskScheduler Runnable方式

public class Task4 implements Runnable {

    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    private static Log logger = LogFactory.getLog(Task4.class);

    @Override
    public void run() {
        logger.info("Task4================" + new Date());
    }

    /**
     * 設定cron並啟動
     * @param cronExp cron值
     */
    public void reStart(String cronExp) {
        if (null != this.threadPoolTaskScheduler) {
            ScheduledExecutorService scheduledExecutorService = this.threadPoolTaskScheduler.getScheduledExecutor();
            if (!scheduledExecutorService.isShutdown()) {
                scheduledExecutorService.shutdownNow();
            }

            this.threadPoolTaskScheduler.destroy();
        }

        if (null != cronExp && cronExp.trim().length() > 0) {
            this.threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
            this.threadPoolTaskScheduler.setThreadNamePrefix("task4");
            this.threadPoolTaskScheduler.initialize();
            this.threadPoolTaskScheduler.schedule(this, new CronTrigger(cronExp));
        }
    }
}

其中reStart可以進行任務啟動和重新設定任務排程時間,呼叫方式如下所示

/**
     * 初始化task4
     * 這裡的程式碼不應該寫在rest層上, 應該寫在service層上
     */
    @PostConstruct
    private void initTask4() {
        //初始化task4任務排程器cron,可以從資料庫中查詢到cron值
        setTask4Cron("0/3 * * * * ?");
    }

    /**
     * 改變task4的cron
     * @param cron cron值
     * @return 成功標誌
     */
    @RequestMapping(value = { "/setTask4Cron" }, method = RequestMethod.GET)
    @ResponseBody
    public String setTask4Cron(String cron) {
        if (null == task4) {
            task4 = new Task4();
        }

        task4.reStart(cron);
        return "success";
    }

initTask4方法加了@PostConstruct’註解,可以在專案啟動時自動根據cron來啟動任務,setTask4Cron方法可以重新調置任務時間

四個任務的效果如下: