本文不阐述quartz与spring集成,没有任何意义,以下内容的整理,全部是我根据https://www.w3cschool.cn/quartz_doc/整理出来
新建一个普通的java工程
1.POM文件,需要引入两个依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.3</version>
</dependency>
2.去quartz官网,下载2.2.3版本的quartz(不要问为什么POM文件依赖了还下载干嘛,因为要用里面的一个sql文件)
去quartz-2.2.3\docs\dbTables文件夹下,找到自己的数据库对应的sql文件,我的是mysql,所以我需要运行tables_mysql.sql文件
3.在普通java工程的src文件夹下建一个叫做quartz.properties的文件,如果不建立这个文件,那么quartz会使用quartz-2.2.3.jar下org.quartz包下的quartz.properties的文件,但是如果使用这个默认文件,那么此篇文章就木有意义了,因为我记录的是集群的搭建,而不是单机
#==============================================================
#Configure Main Scheduler Properties
#==============================================================
集群名称,同一个集群下,所有实例的名字instanceName必须相同,只有这样,一个节点挂掉,另一个节点才能替它工作
org.quartz.scheduler.instanceName = quartzScheduler
实例(节点)ID,同一个集群下,每个节点ID应该都是不一样的,写AUTO,则会像UUID一样,自动生成一个,但是:【经过我自己测试发现,两个不同的节点,instanceId相同竟然也可以正常运行】
org.quartz.scheduler.instanceId = AUTO
#==============================================================
#Configure JobStore 我自己认为JobStore就是元数据管理,把这些元数据存到数据库中
#==============================================================
使用TXJobStore,不同的JobStore针对不同的事务,具体我并没有深入,不过基本都用TX
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
Driver delegates 了解不同数据库系统的特定方言,StdJDBCDelegate用于完全符合JDBC的驱动程序
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
数据库表前缀,假如数据库中有多组quartz表的时候才会使用,如果只有一组,没什么用
org.quartz.jobStore.tablePrefix = QRTZ_
这个属性非常重要,必须为true,表示开启集群支持
org.quartz.jobStore.isClustered = true
检测集群中其他节点是否还活着的频率,10秒,不需要改,参考刘杰分布式理论
org.quartz.jobStore.clusterCheckinInterval = 10000
此处需要注意,这个myDS,其实是在下面org.quartz.dataSource中使用的,这是自己随便写的,如果这里写org.quartz.jobStore.dataSource = aaaaa,那么下面的,比如org.quartz.dataSource.myDS.driver 也要改成org.quartz.dataSource.aaaaa.driver
org.quartz.jobStore.dataSource = myDS
#==============================================================
#Configure DataSource 数据源没什么要说的
#==============================================================
org.quartz.dataSource.myDS.driver = com.mysql.cj.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://127.0.0.1:3306/swttest?serverTimezone=UTC&&useSSL=false
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password =
org.quartz.dataSource.myDS.maxConnections = 30
#==============================================================
#Configure ThreadPool 线程池,我也不了解threadPriority和threadsInheritContextClassLoaderOfInitializingThread
#==============================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
4.现在我要实现一个业务:每隔3秒打印一次"GG",打印开始之前打印"开始打印",打完GG之后,打印"结束打印"
4.1创建一个打印类,专门用来打印"GG",它必须实现Job接口
public class QuartzJob implements Job {
//有相对应的set方法,则能自动注入到这里,下面的TestMain类会说明
private String tutu;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// String value1=context.getJobDetail().getJobDataMap().getString("tutu1");
// 此处不解释,解释也解释不明白,直接参考上面文档即可,就是job和trigger,谁后put就取谁值
// String value4=context.getMergedJobDataMap().getString("tutu3");
System.out.println(tutu);//因为自动注入,所以能打印出来
}
/**
* 如果有set方法,并且创建jobdetail的时候,添加了JobDataMap,则会自动注入
*/
public void setTutu(String tutu1) {
this.tutu = tutu1;
}
}
4.2 创建一个监听器类,实现打印GG前打印"开始打印",打完GG之后,打印"结束打印"
public class MyJobListener implements JobListener{
@Override
public String getName() {
return "随便写";
}
@Override
public void jobToBeExecuted(JobExecutionContext context) {
System.out.println(context.getJobDetail().getKey().getName()+"开始");
}
@Override
public void jobExecutionVetoed(JobExecutionContext context) {
}
@Override
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
System.out.println(context.getJobDetail().getKey().getName()+"完成");
}
}
4.3运行,此处代码其实不多,但是我自己多写了一些,仔细看还是能看懂的
public class TestMain {
public static void main(String[] args) throws SchedulerException, InterruptedException {
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
Scheduler sched =schedFact.getScheduler();
sched.getListenerManager().addJobListener(new MyJobListener());
sched.start();
Map<String,String> p1=new HashMap<>();
p1.put("tutu", "奶糖G1");
addJob(null,QuartzJob.class,"0/2 * * * * ?","G1",sched,p1);
}
public static void addJob(String startTime,Class<? extends Job> jobClazz,String cron,String groupName,Scheduler sched,Map<String,String> param) throws SchedulerException {
Trigger trigger=createCronTrigger(null,cron,groupName);
JobDetail job=createJobDetail(jobClazz,param,groupName);
sched.scheduleJob(job, trigger);
}
public static void delJob(String groupName,Scheduler sched) throws SchedulerException {
JobKey jobkey=new JobKey("myJob1", groupName);
sched.deleteJob(jobkey);
}
public static void editJobTime(String groupName,Scheduler sched) throws SchedulerException {
TriggerKey triggerKey=TriggerKey.triggerKey("myTrigger1", groupName);
Trigger trigger=createCronTrigger(null,"0/1 * * * * ?",groupName);
sched.rescheduleJob(triggerKey, trigger);
}
public static Trigger createCronTrigger(String startTime,String cron,String groupName) {
TriggerBuilder<Trigger> tb= TriggerBuilder.newTrigger();
tb.withIdentity("myTrigger1", groupName);
if(startTime!=null) {
tb.startNow();//TODO
}
tb.withSchedule(CronScheduleBuilder.cronSchedule(cron));
return tb.build();
}
public static JobDetail createJobDetail(Class<? extends Job> jobClazz,Map<String,String> param,String groupName) {
JobBuilder jb = JobBuilder.newJob(jobClazz);
if(param!=null && !param.isEmpty()) {
JobDataMap jobDataMap=new JobDataMap(param);
jb.setJobData(jobDataMap);
}
jb.withIdentity("myJob1", groupName);
return jb.build();
}
}