Quartz定时框架的持久化

小强的上一篇quartz文章简单的说了一下quartz的怎样使用,一般在实际工作中那个根本是不够的,所以今天在这记录下Quartz定时框架的持久化,

一、quartz的存储于持久化介绍

Quartz框架有两种任务存储方式。一种是RAMJobStore存储方式,也是默认的存储方式。RAMJobStore将quartz定时的任务信息存储在服务器的内存中,这种方式的优点是可以提供最好的性能,因为任务信息都存储在内存中访问获取数据速度快。缺点是当服务器突然崩溃了再次重启后你的定时任务也就没有了。另一种是JDBC任务(作业)存储方式,这种方式是将任务信息存储在数据库中,当服务器突然崩溃了再次重启后你的任务还是会接着上次继续执行的,不过需要配置一个quartz.propertity的配置文件(后面会讲到)。
例如:设置了一个50次的的任务当执行了20次后服务器崩溃了,如果采用RAMJobStore存储方式那么在重启后你的定时任务也就没有了,如需执行那就得重新设置50次的定时任务,如果采用了JDBC任务存储的方式那么在你服务器重启后你可以不用重新设置你的定时任务,因为你的定时任务存储在服务器中可以继续接着运行第21次、22次...这就是任务的持久化。

二、持久化示例

从下载的压缩包包中找到你是所使用数据库对应的.sql文件也就是所需要的各种表一般表的地址都在 quartz-2.2.3\docs\dbTables中.(注意你需要将sql文件里的数据库名字改成你自己的库名,至于怎样找到库名可以打开sql文件翻译一下最上面的注释)

在这里解释一下每个表所对应的意思,字段名字太多就不写了可以自己百度一下
表名 含义
QRTZ_BLOB_TRIGGERS 以Blob 类型存储的触发器
QRTZ_CALENDARS 存放日历信息, quartz可配置一个日历来指定一个时间范围
QRTZ_CRON_TRIGGERS 存放cron类型的触发器。
QRTZ_FIRED_TRIGGERS 存放已触发的触发器
QRTZ_JOB_DETAILS 存放一个jobDetail信息
QRTZ_LOCKS 存储程序的悲观锁的信息(假如使用了悲观锁)
QRTZ_PAUSED_TRIGGER_GRPS 存放暂停掉的触发器
QRTZ_SCHEDULER_STATE 调度器状态
QRTZ_SIMPLE_TRIGGERS 简单触发器的信息
QRTZ_TRIGGERS 触发器的基本信息

2、 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: Mscheduler
    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: 3  
    org.quartz.threadPool.threadPriority: 5  
    org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true  
       
    #============================================================================  
    # Configure JobStore  
    #============================================================================  
       
    org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX  
    org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.MSSQLDelegate  
    org.quartz.jobStore.useProperties:false  
    org.quartz.jobStore.isClustered = false 
    org.quartz.jobStore.tablePrefix = QRTZ_    
    org.quartz.jobStore.dataSource:mySqlServer 
    org.quartz.jobStore.maxMisfiresToHandleAtATime=1 
    org.quartz.jobStore.misfireThreshold: 60000  
    org.quartz.jobStore.clusterCheckinInterval:20000       
       
    #============================================================================  
    # Configure Datasources  
    #============================================================================   
	org.quartz.dataSource.mySqlServer.driver = com.microsoft.sqlserver.jdbc.SQLServerDriver
	org.quartz.dataSource.mySqlServer.URL = jdbc:sqlserver://localhost:1433;DatabaseName=test;SelectMethod=cursor
	org.quartz.dataSource.mySqlServer.user = sa	
	org.quartz.dataSource.mySqlServer.password = 123456
	org.quartz.dataSource.mySqlServer.maxConnections = 10
	org.quartz.dataSource.mySqlServer.validationQuery=select count(0) from

Quartz的属性配置文件主要包括三方面的信息:
1)集群信息;
2)调度器线程池;
3)任务调度现场数据的保存。

集群信息:
(1) org.quartz.scheduler.instanceName: Mscheduler 表示调度器的实例名,可以是任何字符串。用来在用到多个调度器区分特定的调度器实例
(2) org.quartz.scheduler.instanceId = AUTO 表示调度器的实例ID在所有调度器实例中必须是唯一的同样也可以是任何字符串,AUTO代表是Quartz框架自动帮你生成

调度器线程池;
(1)org.quartz.threadPool.class:org.quartz.simpl.SimpleThreadPool 表示线程池的实现类(一般使用 SimpleThreadPool即可满足几乎所有用户的需求)
(2) org.quartz.threadPool.threadCount: 3 指定线程数量,至少为1(无默认值)
(3)org.quartz.threadPool.threadPriority:5 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY10,最小为Thread.MIN_PRIORITY 1,默认为5)
(4)org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true 是否自创建父线程

任务存储设置
(1)org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX 调度器信息存储设置在这是存储在数据库( org.quartz.simpl.RAMJobStore为存储在内存中)
(2) org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.MSSQLDelegate 数据库平台类似于Hibernate的dialect,用于处理DB之间的差异(每种数据库都是不同,后边会写出来)
(3) org.quartz.jobStore.useProperties:false 设置TRUE不会出现序列化非字符串类到 BLOB 时产生的类版本问题
(4)org.quartz.jobStore.isClustered = false 是否加入集群
(5) org.quartz.jobStore.tablePrefix = QRTZ_ 设置表的前缀(默认QRTZ_)
(6)org.quartz.jobStore.dataSource:mySqlServer 数据库别名 随便取
(7)org.quartz.jobStore.maxMisfiresToHandleAtATime=1 jobStore处理未按时触发的Job的数量
(8)org.quartz.jobStore.misfireThreshold: 60000 容许的最大作业延长时间
(9)org.quartz.jobStore.clusterCheckinInterval:20000 调度实例失效的检查时间间隔

数据库配置信息(这个就不一一解释了)
(1)org.quartz.dataSource.mySqlServer.driver = com.microsoft.sqlserver.jdbc.SQLServerDriver
(2)org.quartz.dataSource.mySqlServer.URL = jdbc:sqlserver://localhost:1433;DatabaseName=test;SelectMethod=cursor
(3)org.quartz.dataSource.mySqlServer.user = sa
(4)org.quartz.dataSource.mySqlServer.password = 123456
(5)org.quartz.dataSource.mySqlServer.maxConnections = 10 连接池中最大连接数
(6org.quartz.dataSource.mySqlServer.validationQuery=select count(0) from) 设置加锁的SQL语句


org.quartz.jobStore.driverDelegateClass数据库平台

在这里插入图片描述

3、main方法执行类

package quartz;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.quartz.CronScheduleBuilder;
import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;

public class ScheduleMain {
	public static void main(String[] args) throws SchedulerException {
		resumeJob();
		//addJob();
	}	
	//添加一个任务
	public static void addJob() throws SchedulerException {

		// 通过 schedulerFactory 获取一个调度器
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler scheduler = sf.getScheduler();
		
		// 创建 jobDetail 实例,绑定 Job 实现类
        // 指明 job 的名称,所在组的名称,以及绑定 job 类
		JobDetail job = JobBuilder.newJob(TimerJob.class).withIdentity("Job7","group2").build();
		
		// 定义调度触发规则
        // (1)SimpleTrigger,从当前时间的下 1 秒开始,每隔 1 秒执行 1 次,重复执行 2 次
		//TriggerBuilder<SimpleTrigger> trigger = TriggerBuilder.newTrigger()
//				Trigger trigger = (Trigger) TriggerBuilder.newTrigger()
//					// 指明 trigger 的 name 和 group
//					.withIdentity("trigger4", "group1")
//					// 从当前时间的下 1 秒开始执行,默认为立即开始执行(.startNow())
//					.startNow()
//					.startAt(DateBuilder.evenSecondDate(new Date()))
//					.withSchedule(SimpleScheduleBuilder.simpleSchedule()
//					.withIntervalInSeconds(5) // 每隔 1 秒执行 1 次
//					.withRepeatCount(50)) // 重复执行 2 次,一共执行 3 次
//					.build();
		//(2)corn 表达式,先立即执行一次,然后每隔 5 秒执行 1 次
		Trigger trigger = (Trigger) TriggerBuilder.newTrigger()
				.withIdentity("trigger7","group2")
				.withSchedule(CronScheduleBuilder.cronSchedule("0/1 * * * * ?"))//[秒] [分] [时] [每月的第几日] [月] [每周的第几日] [年]
				.build();
		  // 初始化参数传递到 job
		job.getJobDataMap().put("myDescription", "come on");
		job.getJobDataMap().put("myValue", 1990);
		List<String> list = new ArrayList<>();
	        list.add("firstItem");
	    job.getJobDataMap().put("myArray", list);
	    
	    // 把作业和触发器注册到任务调度中
	    scheduler.scheduleJob(job,trigger);
	    
	    // 启动计划程序(实际上直到调度器已经启动才会开始运行)
	    scheduler.start();

        try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        // 等待作业执行完成时才关闭调度器
        //scheduler.shutdown(true);
	}
	//从数据库中找到已经存在的job,并重新开户调度 
	public static void resumeJob() {
		try {  
            SchedulerFactory schedulerFactory = new StdSchedulerFactory();  
            Scheduler scheduler = schedulerFactory.getScheduler();  
            //获取调度器中所有的触发器组  
            List<String> triggerGroups = scheduler.getTriggerGroupNames();  
            //遍历获取每个触发器组
            for (int i = 0; i < triggerGroups.size(); i++) { 
                List<String> triggers = scheduler.getTriggerGroupNames();  
                //遍历每个触发器组 
                for (int j = 0; j < triggers.size(); j++) {  \
	            //获取每个触发器
                    Trigger tg = scheduler.getTrigger(new TriggerKey(triggers  
                            .get(j), triggerGroups.get(i)));  
                    // 重新恢复在tgroup1组中,名为trigger1_1触发器的运行 
                    if (tg instanceof SimpleTrigger  
                            && tg.getDescription().equals("group1.trigger1")) {  
                        //恢复运行  
                        scheduler.resumeJob(new JobKey(triggers.get(j),  
                                triggerGroups.get(i)));  
                    }  
                }  
  
            }  
            scheduler.start();  
        } catch (Exception e) {  
            e.printStackTrace();  
  
        } 
	}
}

4、Job任务类

扫描二维码关注公众号,回复: 3434575 查看本文章
package quartz;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;


/*
 * 
 * 定义需要执行的任务。该类是一个接口,只定义一个方法 execute(JobExecutionContext context)
	在实现类的 execute 方法中编写所需要定时执行的 Job(任务), JobExecutionContext 类提供了调度应用的一些信息。
	Job 运行时的信息保存在 JobDataMap 实例中。
 */
public class TimerJob implements Job {

	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		// 从 context 中获取 instName, groupName 以及 dataMap
		String insName = context.getJobDetail().getKey().getName();
		String groupName = context.getJobDetail().getKey().getGroup();
		JobDataMap dataMap = context.getJobDetail().getJobDataMap();
		
		 // 从 dataMap 中获取 myDescription, myValue 以及 myArray
		String myDescription = dataMap.getString("myDescription");
		int myValue = dataMap.getInt("myValue");
		List<String> myArray = (List<String>)dataMap.get("myArray");
		//打印JobDetail和JobDataMap的信息
		System.out.println("---> Instance = " + insName + ", group = " + groupName+", description = " 
				+ myDescription + ", value =" + myValue+" , array item[0] = " + myArray.get(0));

	}
}

5、执行结果

执行结果

三、结尾

好了,这就是quartz框架的持久化,在这个过程中会遇到好多问题及困难。但是请记住千万不要气馁只要死磕下去你就会成功的。小强会在下一篇中说说quartz任务的动态增删改查以及在学习quartz中遇到的问题及怎样解决。如有兴趣请给个关注点个赞,也算给小强一点激励吧毕竟一个人还是很孤单的。

上一篇 Quartz定时框架

下一篇 Quartz定时任务动态增删改查

本文属于原创如有转载请标明原文链接:https://blog.csdn.net/little__SuperMan/article/details/82749103

猜你喜欢

转载自blog.csdn.net/little__SuperMan/article/details/82749103