> 文章列表 > Springboot整合Quartz定时任务框架(Spring解决方案)

Springboot整合Quartz定时任务框架(Spring解决方案)

Springboot整合Quartz定时任务框架(Spring解决方案)

目录

前言

介绍

集成

POM依赖

基础配置

1、配置数据源

2、配置JOB实例触发器

3、配置SchedulerJobFactory

4、配置SchedulerFactoryBean

业务集成

job编写

接口编写 

接口实现


前言

系统现在有定时任务触发业务场景的需求,并且频率及次数不固定,即可以动态定义任务的频率及次数,因项目本身还是基于springboot开发,暂定还是使用Quartz,后期再升级,单独的Quartz配置有些问题,主要介绍springboot提供的集成方式。

介绍

多的不多,说一下quartz的表结构

 

  • QRTZ_BLOG_TRIGGERS    Trigger 作为 Blob 类型存储
  • QRTZ_CALENDARS    以 Blob 类型存储 Quartz 的 Calendar 信息
  • QRTZ_CRON_TRIGGERS    存储 Cron Trigger,包括 Cron 表达式和时区信息
  • QRTZ_FIRED_TRIGGERS    存储与已触发的 Trigger 相关的状态信息
  • QRTZ_PAUSED_TRIGGER_GRPS    存储已暂停的 Trigger 组的信息
  • QRTZ_SCHEDULER_STATE    存储少量的有关 Scheduler 的状态信息,和别的 Scheduler 实例
  • QRTZ_SIMPLE_TRIGGERS    存储简单的 Trigger,包括重复次数,间隔,以及已触的次数
  • QRTZ_TRIGGERS    存储已配置的 Trigger 的信息
  • QRTZ_LOCKS    存储程序的非观锁的信息(假如使用了悲观锁)
  • QRTZ_JOB_DETAILS    存储每一个已配置的 Job 的详细信息

集成

废话不多说,直接开搞

POM依赖

使用springboot-starter的依赖


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

配置文件

基础配置

如果不想让业务的库客quartz的库在一起,可以这么做

1、配置数据源

@QuartzDataSource可以标记为quartz的库,配置数据源和事务管理器

@Configuration
public class SchedulerDataSourceConfig {private static final String QUARTZ_DATASOURCE = "spring.scheduler.datasource";@Bean@ConfigurationProperties(QUARTZ_DATASOURCE)public DataSourceProperties schedulerProperties() {return new DataSourceProperties();}@QuartzDataSource@Beanpublic DataSource quartzDataSource(DataSourceProperties schedulerProperties) {return schedulerProperties.initializeDataSourceBuilder().build();}@Beanpublic PlatformTransactionManager transactionManager(@Qualifier("quartzDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}

配置文件:

spring:scheduler:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://***/quartzusername: rootpassword: ****type: com.mysql.cj.jdbc.MysqlDataSourcequartz:job-store-type: jdbcjdbc:initialize-schema: alwayscomment-prefix: #properties:org:quartz:jobStore:class: org.springframework.scheduling.quartz.LocalDataSourceJobStoredriverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #我们仅为数据库制作了特定于数据库的代理useProperties: false #以指示JDBCJobStore将JobDataMaps中的所有值都作为字符串,因此可以作为名称 - 值对存储而不是在BLOB列中以其序列化形式存储更多复杂的对象。从长远来看,这是更安全的,因为您避免了将非String类序列化为BLOB的类版本问题。tablePrefix: scheduler_  #数据库表前缀misfireThreshold: 60000 #在被认为“失火”之前,调度程序将“容忍”一个Triggers将其下一个启动时间通过的毫秒数。默认值(如果您在配置中未输入此属性)为60000(60秒)。clusterCheckinInterval: 5000 #设置此实例“检入”*与群集的其他实例的频率(以毫秒为单位)。影响检测失败实例的速度。isClustered: true #打开群集功能threadPool: #连接池class: org.quartz.simpl.SimpleThreadPoolthreadCount: 4threadPriority: 5threadsInheritContextClassLoaderOfInitializingThread: true

2、配置JOB实例与触发器

JobDetailFactoryBean 是spring退出的quartz解决方案,用来产生job。

SpringBoot触发器分类分别为 

SimpleTriggerFactoryBean:简单触发器,通过配置间隔时间实现

CronTriggerFactoryBean:  cron触发器,key通过配置cron表达式来实现

@Configuration
public class JobConfig {@BeanJobDetailFactoryBean dailyJob() {JobDetailFactoryBean bean = new JobDetailFactoryBean();bean.setJobClass(DailyJobExecutor.class);bean.setDurability(true);return bean;}@BeanCronTriggerFactoryBean dailyTrigger(@Qualifier("dailyJob") JobDetail jobDetail) {CronTriggerFactoryBean bean = new CronTriggerFactoryBean();bean.setJobDetail(jobDetail);//cron 每日一次bean.setCronExpression("0 0 0 * * ?");return bean;}@BeanSimpleTriggerFactoryBean simpleTrigger(@Qualifier("dailyJob") JobDetail jobDetail) {SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();bean.setJobDetail(jobDetail);//多少秒一次bean.setRepeatInterval(5000L);bean.setStartDelay(5000L);return bean;}
}

3、配置SchedulerJobFactory

因为我们最终写的job对象最终是new出来quartz管理的,如果在里面使用 @Autowired等spring的注解不会生效,所以配置spring工厂,把实例交给spring管理

@Component
public class SchedulerJobFactory extends SpringBeanJobFactory {@Resourceprivate AutowireCapableBeanFactory capableBeanFactory;@NotNull@Overrideprotected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {Object jobInstance = super.createJobInstance(bundle);// 进行注入(Spring管理该Bean)capableBeanFactory.autowireBean(jobInstance);return jobInstance;}
}

4、配置SchedulerFactoryBean

定时工厂,将我们配置的触发器、数据源、job工厂都注入进来

@Configuration
public class SchedulerConfig {@javax.annotation.Resourceprivate List<CronTriggerFactoryBean> cronTriggerFactoryBeans;@Beanpublic SchedulerFactoryBean schedulerFactoryBean (@Qualifier("quartzDataSource") DataSource dataSource,@Qualifier("schedulerJobFactory") JobFactory jobFactory,@Qualifier("quartzTransactionManager")PlatformTransactionManager transactionManager) throws Exception {SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();schedulerFactoryBean.setBeanName("order-scheduler");schedulerFactoryBean.setDataSource(dataSource);Resource resource = new PathMatchingResourcePatternResolver().getResources("classpath*:/application-scheduler.yml")[0];schedulerFactoryBean.afterPropertiesSet();schedulerFactoryBean.setConfigLocation(resource);schedulerFactoryBean.setJobFactory(jobFactory);schedulerFactoryBean.setTransactionManager(transactionManager);schedulerFactoryBean.setTriggers();CronTrigger[] triggers = cronTriggerFactoryBeans.stream().map(CronTriggerFactoryBean::getObject).toArray(CronTrigger[]::new);schedulerFactoryBean.setTriggers(triggers);return schedulerFactoryBean;}
}

业务集成

job编写

上面JobConfig里面配置的job执行类,因为我用的触发器为cron触发,频率为每天一次,因此为了解耦,每个需要每天执行的job都可以使用这个,注入了接口 DailyJobService, 有多个实现

@Slf4j
@DisallowConcurrentExecution
@PersistJobDataAfterExecution
@Component
public class DailyJobExecutor extends QuartzJobBean {@Resourceprivate List<DailyJobService> dailyJobServiceList;@Overrideprotected void executeInternal(JobExecutionContext context) {log.info("dailyJobService  start...");dailyJobServiceList.forEach(DailyJobService::execute);}
}

接口编写 

DailyJobService,里面定义了执行方法

@Service
public interface DailyJobService {void execute();
}

接口实现

里面写具体的业务逻辑

@Slf4j
@Service
public class OralTackJobServiceImpl implements DailyJobService {@Overridepublic void execute() {log.info("OralTackJobServiceImpl start....");//业务逻辑}}
}