• SpringBoot 整合 Quartz 实现 对任务进行CRUD


    前言

    公司之前的项目的定时任务都是使用@Schedule注解进行管理的;新需求需要实现对定时任务进行动态管理。后面决定用Quartz框架进行集成,以最小的代码来管理定时任务。

    所需依赖:Springboot  1.xx 或 2.xx-RELEASE 都行, quartz 使用2.3.0版本

    1. <dependency>
    2. <groupId>org.quartz-schedulergroupId>
    3. <artifactId>quartzartifactId>
    4. <version>2.3.0version>
    5. dependency>

    为了简单演示,只创建一个任务类用于修改定时任务实体类即可,创建任务实体类:QuartzBean

    1. @Data
    2. public class QuartzBean implements Serializable {
    3. private static final long serialVersionUID=1L;
    4. @TableId
    5. private String id;
    6. /**
    7. * 任务名称
    8. */
    9. private String jobName;
    10. /**
    11. * 任务执行类
    12. */
    13. private String jobClass;
    14. /**
    15. * 任务时间表达式
    16. */
    17. @NotNull
    18. private String cron;
    19. /**
    20. * 任务启动状态 0 运行中 1 已关闭
    21. */
    22. private Integer status;
    23. /**
    24. * 创建时间
    25. */
    26. private Date createTime;
    27. }

    一、配置Quartz相关配置类

    这里有三个配置类,分别为AutowiringSpringBeanJobFactory.java(主要是为了使得Job任务类运行时,可以注入其他service层)、QuartzConfig.java(quartz配置类,可设置对应的数据源,将schedule创建bean对象等)和 QuartzJobInitializer.java (用于项目启动时,可以从数据库里取出对应的QuartzBean对象,进行任务的自启动)

    1. import org.quartz.spi.TriggerFiredBundle;
    2. import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
    3. import org.springframework.context.ApplicationContext;
    4. import org.springframework.context.ApplicationContextAware;
    5. import org.springframework.scheduling.quartz.SpringBeanJobFactory;
    6. /**
    7. * 功能说明: job配置可注入其他服务类
    8. */
    9. public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
    10. private transient AutowireCapableBeanFactory beanFactory;
    11. @Override
    12. public void setApplicationContext(ApplicationContext context) {
    13. beanFactory = context.getAutowireCapableBeanFactory();
    14. }
    15. @Override
    16. protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
    17. final Object job = super.createJobInstance(bundle);
    18. beanFactory.autowireBean(job);
    19. return job;
    20. }
    21. }

    1. import org.quartz.Scheduler;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.context.annotation.Bean;
    4. import org.springframework.context.annotation.Configuration;
    5. import org.springframework.scheduling.quartz.SchedulerFactoryBean;
    6. /**
    7. * 功能说明: quartz配置类
    8. */
    9. @Configuration
    10. public class QuartzConfig {
    11. /** 暂不使用数据库进行quartz的持久化
    12. @Bean
    13. public Properties properties() throws IOException {
    14. PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
    15. // 对quartz.properties文件进行读取
    16. propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
    17. // 在quartz.properties中的属性被读取并注入后再初始化对象
    18. propertiesFactoryBean.afterPropertiesSet();
    19. return propertiesFactoryBean.getObject();
    20. }
    21. **/
    22. @Bean
    23. public AutowiringSpringBeanJobFactory autowiringSpringBeanJobFactory() {
    24. return new AutowiringSpringBeanJobFactory();
    25. }
    26. @Bean
    27. public SchedulerFactoryBean schedulerFactoryBean() {
    28. SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
    29. schedulerFactoryBean.setAutoStartup(true);
    30. schedulerFactoryBean.setJobFactory(autowiringSpringBeanJobFactory());
    31. // 从application.yml中读取Quartz的配置并设置到SchedulerFactoryBean中
    32. // schedulerFactoryBean.setQuartzProperties(properties());
    33. return schedulerFactoryBean;
    34. }
    35. /**
    36. * 通过SchedulerFactoryBean获取Scheduler的实例
    37. * @param schedulerFactoryBean
    38. * @return
    39. */
    40. @Bean
    41. public Scheduler scheduler(SchedulerFactoryBean schedulerFactoryBean) {
    42. return schedulerFactoryBean.getScheduler();
    43. }
    44. }
    1. @Slf4j
    2. @Component
    3. public class QuartzJobInitializer {
    4. @Autowired
    5. private Scheduler scheduler;
    6. @Autowired
    7. private IQuartzBeanService quartzBeanService;
    8. @Autowired
    9. public QuartzJobInitializer(Scheduler scheduler) {
    10. this.scheduler = scheduler;
    11. }
    12. @PostConstruct
    13. public void init(){
    14. log.info("quartz:默认启动所有开启状态的定时任务");
    15. List quartzBeans = quartzBeanService.selectList(new EntityWrapper<>());
    16. List executeJobs = quartzBeans.stream().filter(f -> QuartzEnums.TaskStatusEnum.RUNNING.getType().equals(f.getStatus())).collect(Collectors.toList());
    17. try {
    18. // 这里将会启动所有定时任务
    19. if (CollUtil.isNotEmpty(executeJobs)) {
    20. executeJobs.forEach(item -> QuartzUtils.createScheduleJob(scheduler, item));
    21. }
    22. }catch (Exception e) {
    23. log.error("自启动定时任务异常: {}",e);
    24. }
    25. }
    26. }

    二、创建QuartzUtils.java类

    QuartzUtils类主要用于底层的创建、修改、删除、立即执行、暂停和恢复任务

    1. mport com.bean.QuartzBean;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.quartz.CronScheduleBuilder;
    4. import org.quartz.CronTrigger;
    5. import org.quartz.Job;
    6. import org.quartz.JobBuilder;
    7. import org.quartz.JobDetail;
    8. import org.quartz.JobKey;
    9. import org.quartz.Scheduler;
    10. import org.quartz.SchedulerException;
    11. import org.quartz.TriggerBuilder;
    12. import org.quartz.TriggerKey;
    13. /**
    14. * 功能说明: 定时任务执行工具类
    15. */
    16. @Slf4j
    17. public class QuartzUtils {
    18. /**
    19. * 创建定时任务 定时任务创建之后默认启动状态
    20. * @param scheduler
    21. * @param quartzBean
    22. */
    23. public static void createScheduleJob(Scheduler scheduler, QuartzBean quartzBean) {
    24. try {
    25. //获取到定时任务的执行类 必须是类的绝对路径名称
    26. //定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类。
    27. Classextends Job> jobClass = (Classextends Job>)Class.forName(quartzBean.getJobClass());
    28. // 构建定时任务信息
    29. JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(quartzBean.getJobName()).build();
    30. // 设置定时任务执行方式
    31. CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCron());
    32. // 构建触发器trigger
    33. CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzBean.getJobName()).withSchedule(scheduleBuilder).build();
    34. scheduler.scheduleJob(jobDetail, trigger);
    35. } catch (ClassNotFoundException e) {
    36. log.error("定时任务类路径出错:请输入类的绝对路径 {}",e.getMessage());
    37. } catch (SchedulerException e) {
    38. log.error("创建定时任务出错: {}", e.getMessage());
    39. }
    40. }
    41. /**
    42. * 根据任务名称暂停定时任务
    43. * @param scheduler
    44. * @param jobName
    45. */
    46. public static void pauseScheduleJob(Scheduler scheduler, String jobName) {
    47. JobKey jobKey = JobKey.jobKey(jobName);
    48. try {
    49. scheduler.pauseJob(jobKey);
    50. } catch (SchedulerException e) {
    51. log.error("暂停定时任务出错: {}", e.getMessage());
    52. }
    53. }
    54. /**
    55. * 根据任务名称恢复定时任务
    56. * @param scheduler
    57. * @param jobName
    58. */
    59. public static void resumeScheduleJob(Scheduler scheduler, String jobName) {
    60. JobKey jobKey = JobKey.jobKey(jobName);
    61. try {
    62. scheduler.resumeJob(jobKey);
    63. } catch (SchedulerException e) {
    64. System.out.println("恢复定时任务出错:"+e.getMessage());
    65. }
    66. }
    67. /**
    68. * 根据任务名称立即运行一次定时任务
    69. * @param scheduler
    70. * @param jobName
    71. */
    72. public static void runOnce(Scheduler scheduler, String jobName){
    73. JobKey jobKey = JobKey.jobKey(jobName);
    74. try {
    75. scheduler.triggerJob(jobKey);
    76. } catch (SchedulerException e) {
    77. System.out.println("运行定时任务出错:"+e.getMessage());
    78. }
    79. }
    80. /**
    81. * 更新定时任务
    82. * @param scheduler
    83. * @param quartzBean
    84. */
    85. public static void updateScheduleJob(Scheduler scheduler, QuartzBean quartzBean) {
    86. try {
    87. //获取到对应任务的触发器
    88. TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName());
    89. //设置定时任务执行方式
    90. CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCron());
    91. //重新构建任务的触发器trigger
    92. CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
    93. trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
    94. //重置对应的job
    95. scheduler.rescheduleJob(triggerKey, trigger);
    96. } catch (SchedulerException e) {
    97. System.out.println("更新定时任务出错:"+e.getMessage());
    98. }
    99. }
    100. /**
    101. * 根据定时任务名称从调度器当中删除定时任务
    102. * @param scheduler
    103. * @param jobName
    104. */
    105. public static void deleteScheduleJob(Scheduler scheduler, String jobName) {
    106. JobKey jobKey = JobKey.jobKey(jobName);
    107. try {
    108. scheduler.deleteJob(jobKey);
    109. } catch (SchedulerException e) {
    110. System.out.println("删除定时任务出错:"+e.getMessage());
    111. }
    112. }
    113. }

    三、创建任务类,即定时任务可执行的类 MyQuartzTask

    1. import lombok.extern.slf4j.Slf4j;
    2. import org.quartz.DisallowConcurrentExecution;
    3. import org.quartz.JobExecutionContext;
    4. import org.quartz.JobExecutionException;
    5. import org.quartz.PersistJobDataAfterExecution;
    6. import org.springframework.scheduling.quartz.QuartzJobBean;
    7. import org.springframework.stereotype.Service;
    8. /**
    9. * 功能说明: 定时任务-MyQuartzTask
    10. */
    11. @Slf4j
    12. @Service
    13. @PersistJobDataAfterExecution
    14. @DisallowConcurrentExecution
    15. public class MyQuartzTask extends QuartzJobBean {
    16. @Override
    17. protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
    18. String jobName = jobExecutionContext.getJobDetail().getKey().getName();
    19. log.info("定时任务【{}】启动成功", jobName);
    20. }

    四、效果演示

    1. @Slf4j
    2. @RestController
    3. @RequestMapping("/quartz")
    4. public class QuartzController {
    5. @Autowired
    6. private Scheduler scheduler;
    7. /**
    8. * 创建定时任务
    9. * @param quartzVO
    10. * @return
    11. */
    12. @GetMapping("/createScheduleJob")
    13. public ResultVO createScheduleJob() {
    14. QuartzBean quartzBean = QuartzBean.builder()
    15. .jobName("任务名称唯一")
    16. .jobClass("com.service.impl.quartz.MyQuartzTask")
    17. .cron("0 0/2 * * * ?")
    18. .build();
    19. QuartzUtils.createScheduleJob(scheduler, quartzBean);
    20. return ResultVOUtil.success();
    21. }
  • 相关阅读:
    CocosCreator3.8研究笔记(十八)CocosCreator UI组件(二)
    vue中使用qrcodejs2-fix生成二维码
    高标准农田可视化
    收藏!环境领域一区期刊最新汇总
    23. python 条件判断嵌套
    场内股票期权和场外期权(附场内期权交易攻略)
    主流接口测试框架对比
    《一周的朋友》
    『ScheduleMaster』快速上手一款高可用的开源分布式任务调度平台
    web前端进阶<7>:3d图像翻转效果
  • 原文地址:https://blog.csdn.net/qq_41831842/article/details/134466596