SpringBoot 整合 Quartz 多任务动态管理

前言

终于抽出时间来写这篇博客了,前段时间用到了调度任务,并且由于要求动态控制,于是就研究了一下,也是遇到了挺多坑,今天来分享一下整合Quartz。
关于Quartz 我在这就不多介绍了,如果有兴趣可以去百度搜索一下。
以往整合Quartz时需要在数据库里面配置对应的表,但是今天我们不那么配置,只需要一张表即可。直奔主题。

建表

create table base_quartz_config
(
    configid     varchar(64)  not null
        primary key,
    quarta_name  varchar(100) null comment '任务名称',
    quarta_group varchar(100) null comment '任务组',
    status       int          null comment '状态',
    quartz_class varchar(200) null comment '类全名',
    remark       varchar(200) null comment '备注',
    createuserid varchar(64)  null comment '创建人',
    expression   varchar(64)  null comment '表达式',
    createtime   datetime     null
)
    collate = utf8_bin;

引入依赖

<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

编写代码

创建调度工厂类

MySchedulerFactory.java:

@Service("MySchedulerFactory")
@Component
public class MySchedulerFactory {
     

    private static Logger logger = LoggerFactory.getLogger(MySchedulerFactory.class);

    @Autowired
    SchedulerFactoryBean schedulerFactoryBean;

    @Autowired
    private BaseQuartzService baseQuartzService;

    /**
     * 任务配置读取服务
     */
    @Autowired
    private BaseQuartzService baseQuartzConfigService;

    public void scheduleJobs() throws SchedulerException {
     
        Scheduler scheduler = getScheduler();
        // 为了避免org.quartz.ObjectAlreadyExistsException,在执行前将scheduler进行清理
        scheduler.clear();
        startJob(scheduler);
    }

    /**
     * 获取scheduler
     *
     * @return
     * @author Java最强的男人
     */
    private Scheduler getScheduler() {
     
        return schedulerFactoryBean.getScheduler();
    }


    /**
     * 项目启动 开启任务
     *
     * @param scheduler
     * @author Java最强的男人
     */
    private void startJob(Scheduler scheduler) {
     
        try {
     
            List<BaseQuartzConfig> jobList = baseQuartzConfigService.findAll();
            for (BaseQuartzConfig config : jobList) {
     
                try {
     
                    // 1-暂停的任务 0-正常运行任务
                    if (1L == config.getStatus()) {
     
                        continue;
                    }
                    String classz = config.getQuartzClass();
                    if (!StringUtils.isEmpty(classz)) {
     
                        @SuppressWarnings("unchecked")
                        Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(classz);
                        JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(config.getConfigid(), config.getQuartaGroup())
                                .build();
                        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(config.getExpression());
                        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(config.getConfigid(), config.getQuartaGroup())
                                .withSchedule(scheduleBuilder).build();
                        scheduler.scheduleJob(jobDetail, cronTrigger);
                    }
                } catch (Exception e) {
     
                    logger.info("定时启动异常:" + config.getQuartaName() + " 异常信息:" + e.getMessage());
                }
            }
        } catch (Exception e) {
     
            e.printStackTrace();
        }
    }

    /**
     * 任务暂停
     *
     * @param id
     * @throws Exception
     * @author Java最强的男人
     */
    public void pauseJob(String id) throws Exception {
     
        Scheduler scheduler = getScheduler();
        BaseQuartzConfig QuartzConfig = baseQuartzConfigService.get(String.valueOf(id));
        JobKey jobKey = JobKey.jobKey(QuartzConfig.getConfigid(), QuartzConfig.getQuartaGroup());
        scheduler.deleteJob(jobKey);
        baseQuartzService.update(id,1);
    }

    /**
     * 任务恢复
     *
     * @param id
     * @throws Exception
     * @author Java最强的男人
     */
    public void resumeJob(String id) throws Exception {
     
        Scheduler scheduler = getScheduler();
        BaseQuartzConfig QuartzConfig = baseQuartzConfigService.get(String.valueOf(id));
        JobKey jobKey = JobKey.jobKey(QuartzConfig.getConfigid(), QuartzConfig.getQuartaGroup());
        Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(QuartzConfig.getQuartzClass());
        JobDetail jobDetail1 = scheduler.getJobDetail(jobKey);
        if (jobDetail1 == null) {
     
            JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(QuartzConfig.getConfigid(), QuartzConfig.getQuartaGroup())
                    .build();
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(QuartzConfig.getExpression());
            CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(QuartzConfig.getConfigid(), QuartzConfig.getQuartaGroup())
                    .withSchedule(scheduleBuilder).build();
            scheduler.scheduleJob(jobDetail, cronTrigger);
            baseQuartzService.update(id,0);
        } else {
     
            scheduler.resumeJob(jobKey);
        }
    }


}

MyJobFactory.java:

@Component
public class MyJobFactory extends AdaptableJobFactory {
     

    private final AutowireCapableBeanFactory capableBeanFactory;

    public MyJobFactory(AutowireCapableBeanFactory capableBeanFactory) {
     
        this.capableBeanFactory = capableBeanFactory;
    }

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
     
        // 调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        // 进行注入
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

创建定时任务监听类:
StartSchedulerListener.java:

@Configuration
public class StartSchedulerListener implements ApplicationListener<ContextRefreshedEvent> {
     


    @Autowired
    public MySchedulerFactory mySchedulerFactory;

    private final MyJobFactory myJobFactory;

    public StartSchedulerListener(MyJobFactory myJobFactory) {
     
        this.myJobFactory = myJobFactory;
    }

    // springboot 启动监听
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
     
        try {
     
            mySchedulerFactory.scheduleJobs();
        } catch (SchedulerException e) {
     
            e.printStackTrace();
        }
    }

    //注入SchedulerFactoryBean
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() {
     
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setStartupDelay(5);//延时5秒启动
        schedulerFactoryBean.setJobFactory(myJobFactory);
        return schedulerFactoryBean;
    }

    @Bean(name = "scheduler")
    public Scheduler scheduler() {
     
        return schedulerFactoryBean().getScheduler();
    }

}

测试:


@Configuration
@Component
@EnableScheduling
public class ScheduleTask1 implements Job {
     
 
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
     
        try {
     
            System.out.print("任务执行1 :");
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
 
        } catch (Exception e) {
     
        	System.out.println(e.getMessage());
        }
        }
}

既然是动态配置,那么还需要编写接口类:

@RestController
@CrossOrigin
@RequestMapping("quartz")
@Api(value = "调度任务管理", tags = "调度任务管理")
public class QuartzController {
     

    @Autowired
    private MySchedulerFactory schedulerFactory;

    @ApiOperation(value = "任务暂停", notes = "任务暂停")
    @PostMapping("pauseJob/{configId}")
    public R pauseJob(@PathVariable String configId) {
     
        try {
     
            schedulerFactory.pauseJob(configId);
            return R.ok();
        } catch (Exception e) {
     
            e.printStackTrace();
            return R.error();
        }
    }

    @ApiOperation(value = "任务恢复", notes = "任务恢复")
    @PostMapping("resumeJob/{configId}")
    public R resumeJob(@PathVariable String configId) {
     
        try {
     
            schedulerFactory.resumeJob(configId);
            return R.ok();
        } catch (Exception e) {
     
            e.printStackTrace();
            return R.error();
        }
    }
}

以上代码就实现了对于调度任务的动态管理。

你可能感兴趣的:(Quartz,quartz)