1. 前言
正如 quartz - 揭开面纱 这篇文章提到过的,jobstore是用来存储调度器需要的信息(触发时间,需要运行的job类等)的。在quartz框架的jobstore存储方式主要支持两种方式:RAMJobStore和JDBCJobStore。本次将重点讨论JDBCJobStore方式。
2. RAMJobStore
RAMJobStore 把数据保存在RAM内存中,如果应用意外奔溃或者服务器宕机了,那么调度器记录的一些待执行的任务数据将会丢失,也就是说不能在预定的时间执行指定的任务。要配置quartz使用RAMJobStore存储方式,只需要在配置文件中增加一项配置即可。
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
3. JDBCJobStore
JDBCJobStore,它以JDBC的方式在数据库中保存数据,由于数据需要经过网络和数据库存储,它的存取速度远不如RAMJobStore,但因为数据持久化的特点,使得在服务器宕机后,任务JOB得以恢复执行。JDBCJobStore 几乎适用于所有的数据库,支持 Oracle, PostgreSQL, MySQL, MS SQLServer, HSQLDB, 和DB2。
(1)在使用JDBCJobStore之前,我们需要在数据库中创建Quartz要使用的表,Quartz提供的建表文件在发布包的 “docs/dbTables” 目录下,本文使用的是MYSQL数据库,所以选用 tables_mysql_innodb.sql 。
(2)配置Quartz。配置文件中指定数据源和jobstore实现类。
org.quartz.scheduler.instanceName=MyScheduler
org.quartz.threadPool.threadCount=3
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix=qrtz_
org.quartz.jobStore.dataSource=myDS
org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/quartz?characterEncoding=utf-8
org.quartz.dataSource.myDS.user=root
org.quartz.dataSource.myDS.password=123456
org.quartz.dataSource.myDS.maxConnections=5
(3)测试。本次实验将配置一个 每隔10秒钟执行一次,共执行5次的触发器,但把触发器注册到已经运行的调度器后,会在一秒钟后关闭调度器。然后隔一段时间后,再执行一段代码启动调度器。
JDBCStoreTest类,注册触发器,1秒钟后关闭调度器
public class JDBCStoreTest {
private static final Logger logger = LoggerFactory.getLogger(JDBCStoreTest.class);
public static void main(String[] args) throws SchedulerException, InterruptedException {
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
schedulerFactory.initialize("quartz.properties"); //加载配置文件
Scheduler scheduler = schedulerFactory.getScheduler();
logger.info("Scheduler Name:" + scheduler.getSchedulerName());
// 调度器开始工作
scheduler.start();
//创建一个job
JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("job_name_myjob").build();
// 每隔10秒钟执行一次,共执行5次
SimpleTrigger trigger = TriggerBuilder.newTrigger().startNow()
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(5, 10))
.build();
// job和trigger注册到scheduler
scheduler.scheduleJob(job, trigger);
Thread.sleep(1000);
logger.info("关闭调度器ing...");
// 关闭调度器,此时调度器将会经过shutting down -> paused -> shutdown complete三种状态
scheduler.shutdown();
}
}
此时,关闭调度器后,打开数据库查看quartz建立的表的数据,可以观察到数据库保存了任务和执行时间的一些信息。
JDBCStoreRebootTest类,该类将重启调度器。观察后台输出。
/**
* 重启调度器
*/
public class JDBCStoreRebootTest {
private static final Logger logger = LoggerFactory.getLogger(JDBCStoreRebootTest.class);
public static void main(String[] args) throws SchedulerException, InterruptedException {
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
schedulerFactory.initialize("quartz.properties"); //加载配置文件
Scheduler scheduler = schedulerFactory.getScheduler();
logger.info("Scheduler Name:" + scheduler.getSchedulerName());
// 调度器开始工作
scheduler.start();
Thread.sleep(2 * 60 * 1000);
logger.info("关闭调度器ing...");
scheduler.shutdown();
}
}
在之前的调度器关闭后1分钟,再重启调度器,可以在后台观察到,调度器在启动后,将会尝试恢复原有的任务,并开始执行之前已经过了触发时间的任务。