Quartz学习--二 Hello Quartz! 和源码分析
我会跟着 第一章 6.2 的图来 进行同步代码编写
-
简单入门示例:
-
创建一个新的java普通工程 引入对应版本jar包:
jar包 maven地址为:
<!-- Quartz jar 包 2.2.1 版本 --> <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> <!-- 若你使用的框架是SpringBoot 需要引入: 这里只是个示例简单程序 所以只需要导入上面两个的依赖就可 --> <!--<dependency>--> <!--<groupId>org.springframework</groupId>--> <!--<artifactId>spring-context-support</artifactId>--> <!--<version>4.1.6.RELEASE</version>--> <!--</dependency>-->
-
自创建任务 (Job)
仅仅需要对 org.quartz.Job 接口进行实现 将来调度器会执行我们重写的execute()方法
package com.ws.quartzdemo1001.job01_HelloWorld; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 实现 quartz 对使用人员开放的 Job接口 */ public class HelloJob implements Job { private static Logger log = LoggerFactory.getLogger(HelloJob.class); @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { log.info("Hello Quartz - Job"); } }
-
编写使用Quartz的代码
package com.ws.quartzdemo1001.job01_HelloWorld; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; public class HelloQuartz { private static Logger logger = LoggerFactory.getLogger(HelloQuartz.class); 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(HelloJob.class) .withDescription("this is my first job01_HelloWorld ") // 设置job相关描述 .withIdentity("hello job01_HelloWorld" ,"normal job01_HelloWorld") // 设置任务 名称和组名 .build(); //创建 JobDetail // 4 创建 trigger CronTrigger trigger = TriggerBuilder.newTrigger() .withDescription("this is my first trigger") //设置 trigger 相关描述 .withIdentity("say hello trigger", "cron trigger") //设置 当前触发其 名字 和归属组名 .startAt(new Date()) // 设置任务启动时间 .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?")) .build(); // 5 将 job01_HelloWorld 和 trigger 绑定 并注册到 调度器 scheduler.scheduleJob(jobDetail,trigger); // 6 启动 调度器 scheduler.start(); logger.info(new Date() +" <<<<<< 启动"); } }
主要编写了:
-
创建了Scheduler 工厂
-
从工厂中获取调度器的实例
-
使用自己实现了Job接口的类 来创建 JobDetail
-
创建触发器 并指定触发规则
-
将JobDetail 和触发器进行绑定放入 调度器中 (或者说注册到scheduler)
-
启动调度器
-
-
执行结果:
-
-
入门示例 (追根溯源)
-
作为一个简单的应用程序 我们使用起来给我最大的感触就是 每个主要实例都有一个特定的创建方法
比如 调度器实例就是依靠 Scheduler工厂而创建出来为我们使用
JobDetail 和Trigger 亦是如此
-
HelloJob代码分析:
接口: org.quartz.Job
// Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) package org.quartz; public interface Job { void execute(JobExecutionContext context) throws JobExecutionException; }
一个任务是一个实现Job接口的类, 且任务类必须含有空构造器
当关联这个任务实例的触发器声明的执行时间到了的时候,调度程序Scheduler 会调用这个execute()方法来执行任务,我们的任务内容就可以在这个方法中执行
JobExecutionContext: 工作执行的上下文 自动传入
实际上在该方法退出之前会设置一个结果对象到 上下文中 ,
来让JobListeners 或者TriggerListeners 获得当前任务执行的状态
-
HelloQuartz 代码分析:
// 1 创建 Scheduler 的工厂 SchedulerFactory schedulerFactory = new StdSchedulerFactory();
创建一个生产调度器的工厂
查看Scheduler 接口源码:
// Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) package org.quartz; import java.util.Collection; public interface SchedulerFactory { Scheduler getScheduler() throws SchedulerException; Scheduler getScheduler(String var1) throws SchedulerException; Collection<Scheduler> getAllSchedulers() throws SchedulerException; }
接口规范了 三个必须实现的方法:
三个方法的作用实际上都是 来获取 调度器实例
-
getScheduler()
-
getScheduler(String schedName) // 返回指定了名字的调度器实例
-
getAllSchedulers()
Scheduler 的实现有 两种:
代码中创建的是 new StdSchedulerFactory() ;
查看 DirectSchedulerFactory 中实现代码:
public class DirectSchedulerFactory implements SchedulerFactory { public static final String DEFAULT_INSTANCE_ID = "SIMPLE_NON_CLUSTERED"; public static final String DEFAULT_SCHEDULER_NAME = "SimpleQuartzScheduler"; private static final boolean DEFAULT_JMX_EXPORT = false; private static final String DEFAULT_JMX_OBJECTNAME = null; private static final DefaultThreadExecutor DEFAULT_THREAD_EXECUTOR = new DefaultThreadExecutor(); private static final int DEFAULT_BATCH_MAX_SIZE = 1; private static final long DEFAULT_BATCH_TIME_WINDOW = 0L; private boolean initialized = false; private static DirectSchedulerFactory instance = new DirectSchedulerFactory(); private final Logger log = LoggerFactory.getLogger(this.getClass()); protected Logger getLog() { return this.log; } protected DirectSchedulerFactory() { } ....
仅从字面意思上理解 DirectSchedulerFactory 就是一个直接的 调度器创建工厂
public static final String DEFAULT_INSTANCE_ID = "SIMPLE_NON_CLUSTERED"; public static final String DEFAULT_SCHEDULER_NAME = "SimpleQuartzScheduler";
开始两行中明确指明 这个直接的工厂 是没有实现分布式集群 而且预期返回 简单的调度器 实例
再对比 StdSchedulerFactory的 源码:
public class StdSchedulerFactory implements SchedulerFactory { public static final String PROPERTIES_FILE = "org.quartz.properties"; public static final String PROP_SCHED_INSTANCE_NAME = "org.quartz.scheduler.instanceName"; public static final String PROP_SCHED_INSTANCE_ID = "org.quartz.scheduler.instanceId"; public static final String PROP_SCHED_INSTANCE_ID_GENERATOR_PREFIX = "org.quartz.scheduler.instanceIdGenerator"; public static final String PROP_SCHED_INSTANCE_ID_GENERATOR_CLASS = "org.quartz.scheduler.instanceIdGenerator.class"; public static final String PROP_SCHED_THREAD_NAME = "org.quartz.scheduler.threadName"; public static final String PROP_SCHED_SKIP_UPDATE_CHECK = "org.quartz.scheduler.skipUpdateCheck"; public static final String PROP_SCHED_BATCH_TIME_WINDOW = "org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow"; public static final String PROP_SCHED_MAX_BATCH_SIZE = "org.quartz.scheduler.batchTriggerAcquisitionMaxCount"; public static final String PROP_SCHED_JMX_EXPORT = "org.quartz.scheduler.jmx.export"; public static final String PROP_SCHED_JMX_OBJECT_NAME = "org.quartz.scheduler.jmx.objectName"; public static final String PROP_SCHED_JMX_PROXY = "org.quartz.scheduler.jmx.proxy"; public static final String PROP_SCHED_JMX_PROXY_CLASS = "org.quartz.scheduler.jmx.proxy.class"; public static final String PROP_SCHED_RMI_EXPORT = "org.quartz.scheduler.rmi.export"; public static final String PROP_SCHED_RMI_PROXY = "org.quartz.scheduler.rmi.proxy"; public static final String PROP_SCHED_RMI_HOST = "org.quartz.scheduler.rmi.registryHost"; public static final String PROP_SCHED_RMI_PORT = "org.quartz.scheduler.rmi.registryPort"; public static final String PROP_SCHED_RMI_SERVER_PORT = "org.quartz.scheduler.rmi.serverPort"; public static final String PROP_SCHED_RMI_CREATE_REGISTRY = "org.quartz.scheduler.rmi.createRegistry"; public static final String PROP_SCHED_RMI_BIND_NAME = "org.quartz.scheduler.rmi.bindName"; public static final String PROP_SCHED_WRAP_JOB_IN_USER_TX = "org.quartz.scheduler.wrapJobExecutionInUserTransaction"; public static final String PROP_SCHED_USER_TX_URL = "org.quartz.scheduler.userTransactionURL"; public static final String PROP_SCHED_IDLE_WAIT_TIME = "org.quartz.scheduler.idleWaitTime"; public static final String PROP_SCHED_DB_FAILURE_RETRY_INTERVAL = "org.quartz.scheduler.dbFailureRetryInterval"; public static final String PROP_SCHED_MAKE_SCHEDULER_THREAD_DAEMON = "org.quartz.scheduler.makeSchedulerThreadDaemon"; public static final String PROP_SCHED_SCHEDULER_THREADS_INHERIT_CONTEXT_CLASS_LOADER_OF_INITIALIZING_THREAD = "org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer"; public static final String PROP_SCHED_CLASS_LOAD_HELPER_CLASS = "org.quartz.scheduler.classLoadHelper.class"; public static final String PROP_SCHED_JOB_FACTORY_CLASS = "org.quartz.scheduler.jobFactory.class"; public static final String PROP_SCHED_JOB_FACTORY_PREFIX = "org.quartz.scheduler.jobFactory"; public static final String PROP_SCHED_INTERRUPT_JOBS_ON_SHUTDOWN = "org.quartz.scheduler.interruptJobsOnShutdown"; public static final String PROP_SCHED_INTERRUPT_JOBS_ON_SHUTDOWN_WITH_WAIT = "org.quartz.scheduler.interruptJobsOnShutdownWithWait"; public static final String PROP_SCHED_CONTEXT_PREFIX = "org.quartz.context.key"; public static final String PROP_THREAD_POOL_PREFIX = "org.quartz.threadPool"; public static final String PROP_THREAD_POOL_CLASS = "org.quartz.threadPool.class"; public static final String PROP_JOB_STORE_PREFIX = "org.quartz.jobStore"; public static final String PROP_JOB_STORE_LOCK_HANDLER_PREFIX = "org.quartz.jobStore.lockHandler"; public static final String PROP_JOB_STORE_LOCK_HANDLER_CLASS = "org.quartz.jobStore.lockHandler.class"; public static final String PROP_TABLE_PREFIX = "tablePrefix"; public static final String PROP_SCHED_NAME = "schedName"; public static final String PROP_JOB_STORE_CLASS = "org.quartz.jobStore.class"; public static final String PROP_JOB_STORE_USE_PROP = "org.quartz.jobStore.useProperties"; public static final String PROP_DATASOURCE_PREFIX = "org.quartz.dataSource"; public static final String PROP_CONNECTION_PROVIDER_CLASS = "connectionProvider.class"; .....
-
-