SpringBoot2 task scheduler 定时任务调度器四种方式

github:https://github.com/chenyingjun/springboot2-task

使用@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创建工厂方式

使用到的jar

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>2.3.0</version>
</dependency>

新建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方法可以重新调置任务时间

四个任务的效果如下:

posted @ 2019-03-17 13:54  cnJun  阅读(1699)  评论(0编辑  收藏  举报