Quartz?
任务调度框架“Quartz”是OpenSymphony开源组织在Job scheduling领域又一个开源项目,是完全由java开发的一个开源的任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。
- 在springboot中通过读取数据库的定时任务信息,动态生成quartz定时任务
- 导入依赖
- quartz-jobs
- spring-boot-starter-quartz
- 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容器。
注意:
- @Configuration不可以是final类型;
- @Configuration不可以是匿名类;
- 嵌套的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);
}