1.quartz是什么?
Quartz 是一个完全由 Java 编写的开源作业调度框架,支持各种灵活的应用方式,并同时支持分布式和集群能力。2.quartz的基本要素
2.quartz的基本要素
Scheduler 代表一个调度容器 JobDetail 表示一个具体的可执行的调度程序
Trigger 代表一个调度参数的配置
Job 表示一个工作,要执行的具体内容
3.quartz结合springboot使用(maven工程)
3.1 引入包 pom文件
<!-- quartz及spring任务支持 --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.13.RELEASE</version> </dependency> <!-- 数据库驱动 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- 使用HikariCP数据库连接池 --> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> </dependency> <!-- 工具 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
3.2 先自定义一个类实现spring的QuartzJobBean并重写executeInternal,该类实现了Job类
@Slf4j public class MyJob extends QuartzJobBean { @Override public void executeInternal(JobExecutionContext context){ log.info("线程【{}】开始执行,时间【{}】",Thread.currentThread().getName(),new Date()); } }
3.3 创建JobDetail,Trigger
@Configuration public class JobDetailAndTriggerConfig { @Bean("myJobDetail") public JobDetailFactoryBean getJobDetail(){ JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean(); //Job的实现类类对象 jobDetailFactoryBean.setJobClass(MyJob.class); //任务的名称,框架需要通过此名称进行关联,所以需要保证唯一性 jobDetailFactoryBean.setName("myJob"); //任务组,默认为“DEFAULT”,取值Scheduler.DEFAULT_GROUP jobDetailFactoryBean.setGroup("myJob Group"); //任务描述信息,可以用来传递字符串参数,但是尽量不要这么干 jobDetailFactoryBean.setDescription("myJob Description"); //类似Map类,可以通过此类的对象向Job的execute方法中传递业务参数 //jobDetailFactoryBean.setJobDataMap(null); //Job执行完后是否继续持久化到数据库,默认为false jobDetailFactoryBean.setDurability(true); return jobDetailFactoryBean; } @Bean("myJobTrigger") public CronTriggerFactoryBean getTrigger(@Qualifier("myJobDetail")JobDetail jobDetail){ //使用cronTrigger CronTriggerFactoryBean triggerFactoryBean = new CronTriggerFactoryBean(); //自定义的jobDetail对象 triggerFactoryBean.setJobDetail(jobDetail); //触发器的名称 triggerFactoryBean.setName("myJobTrigger"); //触发器的任务组 triggerFactoryBean.setGroup("myJobTrigger group"); //触发器的描述信息 triggerFactoryBean.setDescription("myJobTrigger description"); //cron表达式 triggerFactoryBean.setCronExpression("0/3 * * * * ?"); //延迟时间 triggerFactoryBean.setStartDelay(0); //设置misfire的任务策略;MISFIRE_INSTRUCTION_DO_NOTHING则不对misfire的任务做特殊处理,只从当前时间之后的下一次正常调度时间开始执行 triggerFactoryBean.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING); //类似Map类,可以通过此类的对象向Job的execute方法中传递业务参数 //triggerFactoryBean.setJobDataMap(null); return triggerFactoryBean; } }
3.4 创建Scheduler 并注册JobDetail,Trigger,然后启动Scheduler
@Slf4j @Configuration public class QuartzSchedulerConfig { @Autowired private DataSource dataSource; @Bean public SchedulerFactoryBean schedulerFactoryBean(ApplicationContext applicationContext) { //创建调度器工厂 SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean(); //设置覆盖任务 schedulerFactory.setOverwriteExistingJobs(true); schedulerFactory.setDataSource(dataSource); schedulerFactory.setSchedulerName("myTestScheduler"); schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties")); Map<String, Trigger> triggers = applicationContext.getBeansOfType(Trigger.class); Collection<Trigger> triggerList = (null != triggers && !triggers.isEmpty()) ? triggers.values(): Collections.emptyList(); schedulerFactory.setTriggers(triggerList.toArray(new Trigger[triggerList.size()])); //schedulerFactory.setJobFactory();不设置时使用默认的AdaptableJobFactory,可以自定义继承SpringBeanJobFactory // 并且要将createJobInstance()创建的实例交由spring自动注入这样才能在job执行方法中注入spring的其他实例,如使用@Service或其他注解的对象自动注入 return schedulerFactory; } }
3.5 配置quartz配置文件及数据源文件
# 数据源相关配置 spring: datasource: type: com.zaxxer.hikari.HikariDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/mytest?tinyInt1isBit=false&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&zeroDateTimeBehavior=convertToNull username: root password: 123456 hikari: connection-test-query: SELECT 1 FROM DUAL minimum-idle: 3 maximum-pool-size: 24 pool-name: ${spring.application.name}-CP idle-timeout: 10000 leakDetectionThreshold: 2000
#quartz配置 #调度标识名 集群中每一个实例都必须使用相同的名称 (区分特定的调度器实例) org.quartz.scheduler.instanceName=bpsp-service-job #ID设置为自动获取 每一个必须不同 (所有调度器实例中是唯一的) org.quartz.scheduler.instanceId=AUTO #线程数量 org.quartz.threadPool.threadCount=5 #数据保存方式为持久化 (也可以指定使用本地内存) org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX #指定委托类 org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate #设置为TRUE不会出现序列化非字符串类到 BLOB 时产生的类版本问题 org.quartz.jobStore.useProperties=true #容许的最大作业延长时间(超过该事件则为misfire) org.quartz.jobStore.misfireThreshold=60000 #表的前缀 org.quartz.jobStore.tablePrefix=qrtz_ #加入集群 true 为集群 false不是集群 org.quartz.jobStore.isClustered=true #调度实例失效的检查时间间隔 org.quartz.jobStore.clusterCheckinInterval=20000 #自带的管理组件plugin org.quartz.plugin.shutdownHook.class=org.quartz.plugins.management.ShutdownHookPlugin org.quartz.plugin.shutdownHook.cleanShutdown=TRUE org.quartz.plugin.triggHistory.class=org.quartz.plugins.history.LoggingTriggerHistoryPlugin org.quartz.plugin.jobHistory.class=org.quartz.plugins.history.LoggingJobHistoryPlugin #每次获取trigger时加锁(默认false) org.quartz.jobStore.acquireTriggersWithinLock=true
4.运行结果
2019-06-06 17:41:45.030 INFO 7532 --- [eduler_Worker-4] com.example.springbootquartz.job.MyJob : 线程【myTestScheduler_Worker-4】开始执行,时间【Thu Jun 06 17:41:45 CST 2019】 2019-06-06 17:41:45.030 INFO 7532 --- [eduler_Worker-4] o.q.p.history.LoggingJobHistoryPlugin : Job myJob Group.myJob execution complete at 17:41:45 06/06/2019 and reports: null 2019-06-06 17:41:45.042 INFO 7532 --- [eduler_Worker-4] o.q.p.h.LoggingTriggerHistoryPlugin : Trigger myJobTrigger group.myJobTrigger completed firing job myJob Group.myJob at 17:41:45 06/06/2019 with resulting trigger instruction code: DO NOTHING 2019-06-06 17:41:48.026 INFO 7532 --- [eduler_Worker-5] o.q.p.h.LoggingTriggerHistoryPlugin : Trigger myJobTrigger group.myJobTrigger fired job myJob Group.myJob at: 17:41:48 06/06/2019 2019-06-06 17:41:48.026 INFO 7532 --- [eduler_Worker-5] o.q.p.history.LoggingJobHistoryPlugin : Job myJob Group.myJob fired (by trigger myJobTrigger group.myJobTrigger) at: 17:41:48 06/06/2019 2019-06-06 17:41:48.026 INFO 7532 --- [eduler_Worker-5] com.example.springbootquartz.job.MyJob : 线程【myTestScheduler_Worker-5】开始执行,时间【Thu Jun 06 17:41:48 CST 2019】 2019-06-06 17:41:48.026 INFO 7532 --- [eduler_Worker-5] o.q.p.history.LoggingJobHistoryPlugin : Job myJob Group.myJob execution complete at 17:41:48 06/06/2019 and reports: null 2019-06-06 17:41:48.026 INFO 7532 --- [eduler_Worker-5] o.q.p.h.LoggingTriggerHistoryPlugin : Trigger myJobTrigger group.myJobTrigger completed firing job myJob Group.myJob at 17:41:48 06/06/2019 with resulting trigger instruction code: DO NOTHING 2019-06-06 17:41:51.035 INFO 7532 --- [eduler_Worker-1] o.q.p.h.LoggingTriggerHistoryPlugin : Trigger myJobTrigger group.myJobTrigger fired job myJob Group.myJob at: 17:41:51 06/06/2019 2019-06-06 17:41:51.036 INFO 7532 --- [eduler_Worker-1] o.q.p.history.LoggingJobHistoryPlugin : Job myJob Group.myJob fired (by trigger myJobTrigger group.myJobTrigger) at: 17:41:51 06/06/2019 2019-06-06 17:41:51.036 INFO 7532 --- [eduler_Worker-1] com.example.springbootquartz.job.MyJob : 线程【myTestScheduler_Worker-1】开始执行,时间【Thu Jun 06 17:41:51 CST 2019】 2019-06-06 17:41:51.036 INFO 7532 --- [eduler_Worker-1] o.q.p.history.LoggingJobHistoryPlugin : Job myJob Group.myJob execution complete at 17:41:51 06/06/2019 and reports: null