简介
可以用来创建执行数十,数百乃至数万个作业的简单或复杂的计划;开源的完全使用JAVA开发的一种时间调度框架,可多线程同步执行。支持集群、JTA事务(听着好高大上,说白了就是定时器~,与以往不同的是,他支持大量的定时任务同步执行,还可以将定时信息保存到数据库中在需要的时候在开启执行,可以防止数据丢失,也可以随时查看定时任务的信息)
使用
quartz 下载地址: http://www.quartz-scheduler.org/downloads/
quartz有两种使用方式:RAM、JDBC。任务的调度也有两种方式:SimpleSchedule、CronSchedule
RAM方式:
程序直接运行在内存中
1、导入 Quartz 的jar包,官网有zip文件可供下载,maven 项目则需要导入依赖
<!-- quartz begin --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.1</version> </dependency> <!-- quartz end --> <!-- log --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency>
2、创建 quartz.properties 文件放到 classpath 中
#JDBC驱动
#org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
#org.quartz.dataSource.qzDS.URL:jdbc:mysql://localhost:3306/test
#org.quartz.dataSource.qzDS.user:root
#org.quartz.dataSource.qzDS.password:
#org.quartz.dataSource.qzDS.maxConnection:10
org.quartz.scheduler.instanceName=MyScheduler
org.quartz.threadPool.threadCount=3
org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
3、创建具体的任务
package com.quartz.first; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class MyJob implements Job { private static final String NAME = "name"; @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println(" execute job() ... "); } }
调用
package com.quartz.first; import java.util.Date; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; /** * * 使用 RAM 方式定时 * * @author 丰志 * */ public class RAMQuartz { public static void main(String[] args) throws SchedulerException { //1.创建Scheduler的工厂 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); //2.从工厂中获取调度器实例 Scheduler scheduler = schedulerFactory.getScheduler(); //3.创建JobDetail JobDetail jobDetail = JobBuilder.newJob(MyJob.class) .withDescription("this is a ram job") //job的描述 .withIdentity("ramJob", "ramGroup") //job 的name和group .build(); // jobDetail.getJobDataMap().put("name", "zhangsan"); //传参用与MyJob中获取参数 jobDataMap.get("name") //任务运行的时间,SimpleSchedle类型触发器有效 long time= System.currentTimeMillis() + 3*1000L; //3秒后启动任务 Date statTime = new Date(time); //4.创建Trigger //使用SimpleScheduleBuilder或者CronScheduleBuilder Trigger trigger = TriggerBuilder.newTrigger() .withDescription("") .withIdentity("ramTrigger", "ramTriggerGroup") .startAt(statTime) //默认当前时间启动 // .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).withRepeatCount(10)) // 每个2秒钟执行一次,一共执行10次 // .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")) //两秒执行一次,cron 秒、分、时、日、月、年、 .build(); //5.注册任务和定时器 scheduler.scheduleJob(jobDetail, trigger); //6.启动 调度器 scheduler.start(); } }
结果:
到此就实现了基本的调度任务,但是在实际项目中往往需要用到quartz跟一些开发框架的集成
spring集成quartz
使用spring框架来管理quartz可以使开发变得简单,只需要书写具体的任务即可,因为不在需要写JAVA代码来开启任务,spring会根据配置文件中的配置自动开启省去了手写的调度过程。具体实现:
1、添加 spring 支持(添加之前的依赖):
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency>
2、创建具体的任务
Simple方式:
package org.quartz.demo; import java.util.Date; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; public class SimpleJob extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { System.out.println("------ 执行ExampleJob -------" + new Date()); } }
Cron方式:
package org.quartz.demo; import java.util.Date; public class CronJob { public void doIt() { System.out.println("====== 执行 ExampleBusinessObject.doIt... ======" + new Date()); } }
3、配置 spring-quartz.xml 文件:
spring 的applicationContext.xml文件中添加quartz:
<import resource="classpath:conf/spring-quartz.xml" />
配置 spring-quartz.xml
Simple方式:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <!-- 具体执行的任务 --> <bean name="simpleJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="org.quartz.demo.SimpleJob"/> </bean> <!-- Simple触发器 --> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="simpleJob"/> <property name="startDelay" value="50000"/> <property name="repeatInterval" value="5000"/> </bean> <!-- 调度工厂 --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="simpleTrigger"/> </list> </property> </bean> </beans>
Cron方式:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <!-- 具体的任务 --> <bean id="cronJob" class="org.quartz.demo.CronJob"/> <!-- JobDetail --> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="cronJob"/> <property name="targetMethod" value="doIt"/> </bean> <!-- Cron触发器 --> <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="jobDetail"/> <property name="cronExpression" value="10 * * * * ?"/> </bean> <!-- 调度工厂 --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger"/> </list> </property> </bean> </beans>
启动 tomcat 测试结果
Cron.doIt 每分钟的第 10 秒执行一次, SimpleJob 每 5 秒钟执行一次。两个任务可以同时调度。测试通过~
JDBC方式:
如果需要使用 JDBC模式需要下载官方的资料,进入 quartz-2.2.3 / docs / dbTables 里面有所有的 sql 文件,可以执行具体的 sql 生成需要的数据表,数据表只有在使用 JDBC 模式的情况下才有效,这里只是初步的记录下quartz的使用。
1、根据官方文档提供的 sql 生成相应的数据表
在下载文件夹下进入 quartz-2.2.3 / docs / dbTables 执行相应的 sql 生成对应的数据表
其中常用的
qrtz_cron_tiggers: 记录使用 CRON 表达式定义的触发器
qrtz_fired_triggers: 记录触发器的执行时间
qrtz_job_details: 记录具体任务的名称,组,类名等信息
qrtz_simple_triggers: 记录使用 Simple 方式定义的触发器
qrtz_triggers: 记录触发器执行的详细信息,包括任务的名称、组,触发器的名称、组以及触发器的开始执行时间、上次执行的时间和下一次执行的时间等信息
2、配置 quartz.properties 放到 classpath 目录下
org.quartz.threadPool.threadCount=3 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.dataSource = myDS org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/test org.quartz.dataSource.myDS.user = root org.quartz.dataSource.myDS.password = org.quartz.dataSource.myDS.maxConnections = 30
在这儿只列举基本的配置,详细的参考: http://www.quartz-scheduler.org/documentation/quartz-2.1.x/configuration/
3、配置具体的任务
package com.quartz.first; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class MyJob implements Job { private static final String NAME = "name"; @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println(" execute jdbcJob() ... "); } }
4、调用测试
package com.quartz.first; import java.util.List; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; 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.impl.StdSchedulerFactory; public class JDBCQuartz { public static void main(String[] args) throws SchedulerException { startSchedule(); //开始执行定时任务,同时会向数据库写入任务、触发器、调度等数据 //resumeJob(); // 重新执行 } private static void startSchedule() { try { // 1、创建JobDetail实例 JobDetail jobDetail = JobBuilder.newJob(MyJob.class).withIdentity("job1", "group1").build(); // 2、设置触发器类型 、执行次数 // SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.repeatSecondlyForTotalCount(5); CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/2 * * * * ?"); // 3、创建Trigger Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow() .withSchedule(cronScheduleBuilder).build(); // 4、创建Scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.start(); // 5、调度执行 scheduler.scheduleJob(jobDetail, trigger); try { Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } // 关闭调度器 // scheduler.shutdown(); } catch (SchedulerException e) { e.printStackTrace(); } } /** 从数据库中找到已经存在的job,并重新开户调度 */ private static void resumeJob() { try { SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); JobKey jobKey = new JobKey("job1", "group1"); List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey); if (triggers.size() > 0) { for (Trigger tg : triggers) { // 根据类型判断 if ((tg instanceof CronTrigger) || (tg instanceof SimpleTrigger)) { // 恢复job运行 scheduler.resumeJob(jobKey); } } scheduler.start(); } } catch (Exception e) { e.printStackTrace(); } } }
运行结果:
数据库:
关闭服务,执行修改代码执行resumeJob():
一秒钟执行了这么多次,调用成功。
到此基本的使用应该没什么问题了 (~ ̄▽ ̄ ~)
源码: https://files.cnblogs.com/files/guofz/myFirstQuartz.rar
Quartz官方介绍: http://www.quartz-scheduler.org/documentation/quartz-2.2.x/quick-start.html
Spring官方文档介绍集成 Quartz 地址:https://docs.spring.io/spring/docs/4.3.17.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/
最后:欢迎吐槽指正~