比尔云BierYun--阿里云最新优惠活动
阿里云优惠码丨阿里云代金券

spring中使用quartz框架(持久化到数据库+springboot)

spring中使用quartz框架(持久化到数据库+springboot)http://www.bieryun.com/1513.html

本例是在springboot中通过读取数据库的定时任务信息,动态生成quartz定时任务

1、导入依赖:

[html] view plain copy

  1. <dependency>
  2.             <groupId>org.quartz-scheduler</groupId>
  3.             <artifactId>quartz</artifactId>
  4.             <version>2.2.1</version>
  5.         </dependency>
  6.         <dependency>
  7.              <groupId>org.springframework</groupId>
  8.              <artifactId>spring-context-support</artifactId>
  9.              <version>${spring.version}</version>
  10.         </dependency>

2、在项目中添加quartz.properties文件(这样就不会走它自带的properties文件)

[html] view plain copy

  1. # Default Properties file for use by StdSchedulerFactory
  2. # to create a Quartz Scheduler Instance, if a different
  3. # properties file is not explicitly specified.
  4. #
  5. #默认或是自己改名字都行
  6. org.quartz.scheduler.instanceName: DefaultQuartzScheduler
  7. #如果使用集群,instanceId必须唯一,设置成AUTO
  8. org.quartz.scheduler.instanceId = AUTO
  9. org.quartz.scheduler.rmi.export: false
  10. org.quartz.scheduler.rmi.proxy: false
  11. org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
  12. org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
  13. org.quartz.threadPool.threadCount: 10
  14. org.quartz.threadPool.threadPriority: 5
  15. org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
  16. org.quartz.jobStore.misfireThreshold: 60000
  17. #============================================================================
  18. # Configure JobStore
  19. #============================================================================
  20. #
  21. #org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
  22. #存储方式使用JobStoreTX,也就是数据库
  23. org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
  24. org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
  25. #使用自己的配置文件
  26. org.quartz.jobStore.useProperties:true
  27. #数据库中quartz表的表名前缀
  28. org.quartz.jobStore.tablePrefix:qrtz_
  29. org.quartz.jobStore.dataSource:qzDS
  30. #是否使用集群(如果项目只部署到 一台服务器,就不用了)
  31. org.quartz.jobStore.isClustered = true
  32. #============================================================================
  33. # Configure Datasources
  34. #============================================================================
  35. #配置数据源
  36. org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
  37. org.quartz.dataSource.qzDS.URL:jdbc:mysql://10.4.33.251:3306/ecif_orgin
  38. org.quartz.dataSource.qzDS.user:reader1
  39. org.quartz.dataSource.qzDS.password:Reader12341
  40. org.quartz.dataSource.qzDS.maxConnection:10

 

3、在数据库中创建quartz相关的表

1)进入quartz的官网http://www.quartz-scheduler.org/,点击Downloads,下载后在目录\docs\dbTables下有常用数据库创建quartz表的脚本。

2)百度去搜创建quartz表

4、自定义MyJobFactory,解决spring不能在quartz中注入bean的问题

[java] view plain copy

  1. package com.nnfe.ecif.domain.bean;
  2. import org.quartz.spi.TriggerFiredBundle;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
  5. import org.springframework.scheduling.quartz.AdaptableJobFactory;
  6. import org.springframework.stereotype.Component;
  7. @Component
  8. public class MyJobFactory extends AdaptableJobFactory {
  9.       @Autowired
  10.       private AutowireCapableBeanFactory capableBeanFactory;
  11.       @Override
  12.       protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
  13.         Object jobInstance = super.createJobInstance(bundle);
  14.         capableBeanFactory.autowireBean(jobInstance); //这一步解决不能spring注入bean的问题
  15.         return jobInstance;
  16.       }
  17. }

5、创建调度器schedule

[java] view plain copy

  1. package com.nnfe.ecif.config;
  2. import java.io.IOException;
  3. import java.util.Properties;
  4. import org.quartz.Scheduler;
  5. import org.quartz.SchedulerException;
  6. import org.quartz.SchedulerFactory;
  7. import org.quartz.impl.StdSchedulerFactory;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.beans.factory.config.PropertiesFactoryBean;
  10. import org.springframework.context.annotation.Bean;
  11. import org.springframework.context.annotation.Configuration;
  12. import org.springframework.core.io.ClassPathResource;
  13. import org.springframework.scheduling.quartz.SchedulerFactoryBean;
  14. import com.nnfe.ecif.domain.bean.MyJobFactory;
  15. @Configuration
  16. public class QuartzConfigration {
  17.      @Autowired
  18.      private MyJobFactory myJobFactory;  //自定义的factory

[java] view plain copy

  1. //获取工厂bean 
  2.     @Bean
  3.     public SchedulerFactoryBean schedulerFactoryBean() {
  4.       SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
  5.       try {
  6.         schedulerFactoryBean.setQuartzProperties(quartzProperties());
  7.         schedulerFactoryBean.setJobFactory(myJobFactory);
  8.     } catch (IOException e) {
  9.         // TODO Auto-generated catch block
  10.         e.printStackTrace();
  11.     }
  12.       return schedulerFactoryBean;
  13.     }

[java] view plain copy

  1. //指定quartz.properties
  2.     @Bean
  3.     public Properties quartzProperties() throws IOException {
  4.         PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
  5.         propertiesFactoryBean.setLocation(new ClassPathResource(“/quartz.properties”));
  6.         propertiesFactoryBean.afterPropertiesSet();
  7.         return propertiesFactoryBean.getObject();
  8.     }
  9. //创建schedule  
  10.     @Bean(name = “scheduler”)
  11.     public Scheduler scheduler() {
  12.       return schedulerFactoryBean().getScheduler();
  13.     }
  14. }

 

6、更新quartz中的任务

首先我们需要自己创建一张表,用来存放trigger的信息,然后从数据库读取这些信息来随时更新定时任务

现在我的数据库中有两个定时任务,注意:job_name存放的任务类的全路径,在quartz中通过jobName和jobGroup来确定trigger的唯一性,所以这两列为联合唯一索引。

接着创建实体类:

[java] view plain copy

  1. import javax.persistence.Column;
  2. import javax.persistence.Entity;
  3. import javax.persistence.GeneratedValue;
  4. import javax.persistence.GenerationType;
  5. import javax.persistence.Id;
  6. import javax.persistence.Table;
  7. import org.hibernate.annotations.GenericGenerator;
  8. @Entity
  9. @Table(name = “c_schedule_triggers”)
  10. public class CScheduleTrigger {
  11.     @Id
  12.     @GenericGenerator(name = “mysqlNative”, strategy = “native”)
  13.     @GeneratedValue(generator = “mysqlNative”)
  14.       private Integer id;
  15.       @Column
  16.       private String cron;  //时间表达式
  17.       private String status; //使用状态 0:禁用   1:启用
  18.       private String jobName; //任务名称
  19.       private String jobGroup; //任务分组

 

更新quartz中的任务

[html] view plain copy

  1. package com.nnfe.ecif.domain.service.impl;
  2. import java.util.List;
  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.TriggerBuilder;
  11. import org.quartz.TriggerKey;
  12. import org.slf4j.Logger;
  13. import org.slf4j.LoggerFactory;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.context.annotation.Configuration;
  16. import org.springframework.scheduling.annotation.EnableScheduling;
  17. import org.springframework.scheduling.annotation.Scheduled;
  18. import org.springframework.stereotype.Component;
  19. import org.springframework.stereotype.Service;
  20. import com.nnfe.ecif.domain.orm.w.CScheduleTriggerRepository;
  21. import com.nnfe.ecif.domain.orm.w.CScheduleTrigger;
  22. import com.nnfe.ecif.domain.service.ScheduleTriggerService;
  23. @Service
  24. public class ScheduleTriggerServiceImpl implements ScheduleTriggerService{
  25.     private static final Logger logger =  LoggerFactory.getLogger(ScheduleTriggerServiceImpl.class);
  26.     @Autowired
  27.     private Scheduler scheduler;
  28.     @Autowired
  29.     private CScheduleTriggerRepository triggerRepository;
  30.     @Override
  31.     @Scheduled(cron=“0 0 23:00 * * ?”)  //每天晚上11点调用这个方法来更新quartz中的任务
  32.     public void refreshTrigger() {
  33.         try {
  34.             //查询出数据库中所有的定时任务
  35.             List<CScheduleTrigger> jobList = triggerRepository.queryAll();
  36.             if(jobList!=null){
  37.                 for(CScheduleTrigger scheduleJob : jobList){
  38.                     String status = scheduleJob.getStatus(); //该任务触发器目前的状态
  39.                     TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
  40.                     CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
  41.                      //说明本条任务还没有添加到quartz中
  42.                     if (null == trigger) {
  43.                         if(status.equals(“0”)){ //如果是禁用,则不用创建触发器
  44.                             continue;
  45.                         }
  46.                         JobDetail jobDetail=null;
  47.                         try {
  48.                             //创建JobDetail(数据库中job_name存的任务全路径,这里就可以动态的把任务注入到JobDetail中)
  49.                             jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(scheduleJob.getJobName()))
  50.                                 .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).build();
  51.                             //表达式调度构建器
  52.                             CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob
  53.                                 .getCron());
  54.                             //按新的cronExpression表达式构建一个新的trigger
  55.                             trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).withSchedule(scheduleBuilder).build();
  56.                             //把trigger和jobDetail注入到调度器
  57.                             scheduler.scheduleJob(jobDetail, trigger);
  58.                         } catch (ClassNotFoundException e) {
  59.                             // TODO Auto-generated catch block
  60.                             e.printStackTrace();
  61.                         }
  62.                     } else {  //说明查出来的这条任务,已经设置到quartz中了
  63.                         // Trigger已存在,先判断是否需要删除,如果不需要,再判定是否时间有变化
  64.                         if(status.equals(“0”)){ //如果是禁用,从quartz中删除这条任务
  65.                             JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
  66.                             scheduler.deleteJob(jobKey);
  67.                             continue;
  68.                         }
  69.                         String searchCron = scheduleJob.getCron(); //获取数据库的
  70.                         String currentCron = trigger.getCronExpression();
  71.                         if(!searchCron.equals(currentCron)){  //说明该任务有变化,需要更新quartz中的对应的记录
  72.                             //表达式调度构建器
  73.                             CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron);
  74.                             //按新的cronExpression表达式重新构建trigger
  75.                             trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
  76.                                 .withSchedule(scheduleBuilder).build();
  77.                             //按新的trigger重新设置job执行
  78.                             scheduler.rescheduleJob(triggerKey, trigger);
  79.                         }
  80.                     }
  81.                 }
  82.             }
  83.         } catch (Exception e) {
  84.            logger.error(“定时任务每日刷新触发器任务异常,在ScheduleTriggerServiceImpl的方法refreshTrigger中,异常信息:”,e);
  85.         }
  86.     }

 

7、自定义任务

[html] view plain copy

  1. @Component
  2. public class MyTask1 implements Job{
  3.     //这里就可以通过spring注入bean了
  4.     @Autowired
  5.     private CScheduleTriggerRepository jobRepository;
  6.     @Autowired
  7.     private CScheduleRecordsRepository recordsRepository;
  8.     @Override
  9.     public void execute(JobExecutionContext context)
  10.             throws JobExecutionException {
  11.         boolean isExecute = false;  //是否已执行业务逻辑
  12.         boolean flag = false;  //业务逻辑执行后返回结果
  13.         try{
  14.             //可以通过context拿到执行当前任务的quartz中的很多信息,如当前是哪个trigger在执行该任务
  15.             CronTrigger trigger = (CronTrigger) context.getTrigger();
  16.             String corn = trigger.getCronExpression();
  17.             String jobName = trigger.getKey().getName();
  18.             String jobGroup = trigger.getKey().getGroup();

 

要搞清楚一个问题:从数据库读取任务信息动态生成定时任务,和把quartz持久化到数据库是没有关系的。

前者是我们自己定义的业务表,而后者是quartz使用自己的表来存储信息。持久化到数据库后,就算服务器重启或是多个quartz节点也没关系,因为他们共享数据库中的任务信息。

未经允许不得转载:比尔云 » spring中使用quartz框架(持久化到数据库+springboot)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

强烈推荐

高性能SSD云服务器ECS抗攻击,高可用云数据库RDS