目录

前言

介绍

集成

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
    @Bean
    public DataSource quartzDataSource(DataSourceProperties schedulerProperties) {
        return schedulerProperties.initializeDataSourceBuilder().build();
    }

    @Bean
    public PlatformTransactionManager transactionManager(@Qualifier("quartzDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

配置文件:

spring:
  scheduler:
    datasource:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://***/quartz
      username: root
      password: ****
      type: com.mysql.cj.jdbc.MysqlDataSource
  quartz:
    job-store-type: jdbc
    jdbc:
      initialize-schema: always
      comment-prefix: #
    properties:
      org:
        quartz:
          jobStore:
            class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
            driverDelegateClass: 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.SimpleThreadPool
            threadCount: 4
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true

2、配置JOB实例与触发器

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

SpringBoot触发器分类分别为 

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

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

@Configuration
public class JobConfig {

    @Bean
    JobDetailFactoryBean dailyJob() {
        JobDetailFactoryBean bean = new JobDetailFactoryBean();
        bean.setJobClass(DailyJobExecutor.class);
        bean.setDurability(true);
        return bean;
    }

    @Bean
    CronTriggerFactoryBean dailyTrigger(@Qualifier("dailyJob") JobDetail jobDetail) {
        CronTriggerFactoryBean bean = new CronTriggerFactoryBean();
        bean.setJobDetail(jobDetail);
        //cron 每日一次
        bean.setCronExpression("0 0 0 * * ?");
        return bean;
    }

    
    @Bean
    SimpleTriggerFactoryBean 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 {

    @Resource
    private AutowireCapableBeanFactory capableBeanFactory;

    @NotNull
    @Override
    protected 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.Resource
    private List<CronTriggerFactoryBean> cronTriggerFactoryBeans;

    @Bean
    public 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 {

    @Resource
    private List<DailyJobService> dailyJobServiceList;

    @Override
    protected 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 {


    @Override
    public void execute() {


        log.info("OralTackJobServiceImpl start....");

        //业务逻辑
        }
    }
}

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐