Quartz

Quartz?

任务调度框架“Quartz”是OpenSymphony开源组织在Job scheduling领域又一个开源项目,是完全由java开发的一个开源的任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。

  • 在springboot中通过读取数据库的定时任务信息,动态生成quartz定时任务
  • 导入依赖
  1. quartz-jobs
  2. spring-boot-starter-quartz
  3. druid-spring-boot-starter
  • 在项目中添加quartz.properties文件
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#

#默认或是自己改名字都行
org.quartz.scheduler.instanceName: DefaultQuartzScheduler

#如果使用集群,instanceId必须唯一,设置成AUTO
org.quartz.scheduler.instanceId = AUTO

org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000
#============================================================================
# Configure JobStore
#============================================================================
#存储方式使用JobStoreTX,也就是数据库
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#使用自己的配置文件
org.quartz.jobStore.useProperties:true
#数据库中quartz表的表名前缀
org.quartz.jobStore.tablePrefix:qrtz_
org.quartz.jobStore.dataSource:qzDS
#是否使用集群(如果项目只部署到 一台服务器,就不用了)
org.quartz.jobStore.isClustered = true

#============================================================================
# Configure Datasources
#============================================================================
#配置数据源
#org.quartz.dataSource.qzDS.connectionProvider.class:org.quartz.utils.PoolingConnectionProvider
org.quartz.dataSource.qzDS.driver:com.mysql.cj.jdbc.Driver
org.quartz.dataSource.qzDS.URL:jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
org.quartz.dataSource.qzDS.user:root
org.quartz.dataSource.qzDS.password:123
org.quartz.dataSource.qzDS.maxConnections:10

注:(这样就不会加载自带的properties文件)
此文件的内容主要分为:scheduler,ThreadPool,JobStore,plugin,Datasources等部分

  • 在数据库中创建quartz相关的表
  • 进入quartz的官网http://www.quartz-scheduler.org/,点击Downloads
  • 下载后在目录\docs\dbTables下有常用数据库创建quartz表的脚本,例如:“tables_mysql.sql”
  • 自定义MyJobFactory,解决spring不能在quartz中注入bean的问题
@Component
public class MyJobFactory extends AdaptableJobFactory {

    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        Object jobInstance = super.createJobInstance(bundle);//qz框架反射机制创建jobBean
        capableBeanFactory.autowireBean(jobInstance); //这一步解决不能spring注入bean的问题
        return jobInstance;
    }
}

Job是由quartz创建,不是由spring创建
AutowireCapableBeanFactory是spring提供的接口:

对于想要拥有自动装配能力,并且想把这种能力暴露给外部应用的BeanFactory类需要实现此接口。
正常情况下,不要使用此接口,应该更倾向于使用BeanFactory或者ListableBeanFactory接口。此接口主要是针对框架之外,没有向Spring托管Bean的应用。通过暴露此功能,Spring框架之外的程序,具有自动装配等Spring的功能。
需要注意的是,ApplicationContext接口并没有实现此接口,因为应用代码很少用到此功能,如果确实需要的话,可以调用ApplicationContext的getAutowireCapableBeanFactory方法,来获取此接口的实例。
如果一个类实现了此接口,那么很大程度上它还需要实现BeanFactoryAware接口。它可以在应用上下文中返回BeanFactory

  • 创建调度器schedule
@Configuration
public class QuartzConfigration {

    @Autowired
    private MyJobFactory myJobFactory;  //自定义的factory

    //获取工厂bean
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() {//任务调度器由调度器工厂创建
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        try {
            schedulerFactoryBean.setQuartzProperties(quartzProperties());//调度器工厂读取配置文件quartz.properties
            /**
             * Job默认是由quartz框架创建,这里改成了自定义的Job工厂,而这个自定义的工厂已经被注入到spring的上下文中了
             * 解决了Job拿不到spring上下文里的javaBean的问题
             */
            schedulerFactoryBean.setJobFactory(myJobFactory);
            return schedulerFactoryBean;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //指定quartz.properties
    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    //创建schedule
    @Bean(name = "scheduler")//外部程序调用这个方法,得到任务调度器
    public Scheduler scheduler() {
        return schedulerFactoryBean().getScheduler();
    }
}

@Configuration注解
从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,
被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext
或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
注意:

  1. @Configuration不可以是final类型;
  2. @Configuration不可以是匿名类;
  3. 嵌套的configuration必须是静态类。
    @Bean
    一般是跟@Configuration一起配合着使用,用于创建javaBean,将创建出来的javaBean存到spring的上下文中去
  • 创建自定义任务

注1:实现接口org.quartz.Job或org.springframework.scheduling.quartz.QuartzJobBean创建任务,可通过JobExecutionContext传参
更新quartz中的任务
首先我们需要自己创建一张表t_schedule_trigger,用来存放trigger的信息,然后从数据库读取这些信息来随时更新定时任务
注意:job_name存放的任务类的全路径,在quartz中通过jobName和jobGroup来确定trigger的唯一性,所以这两列为联合唯一索引

注1:t_schedule_trigger的子表t_schedule_trigger_param还可以用来传递额外添加到任务中的参数

    @Test
    public void add() throws Exception {
        scheduleTrigger.setId(null);
        scheduleTrigger.setCron("*/5 * * * * ?");
        scheduleTrigger.setStatus("1");
        scheduleTrigger.setJobName("com.howe.q03.quartz.MyJob1");
        scheduleTrigger.setJobGroup("group-1");
        scheduleTriggerService.add(scheduleTrigger);
    }

你可能感兴趣的:(Quartz)