介绍
from:教程https://www.w3cschool.cn/quartz_doc/
Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。
Quartz 可以与 J2EE 与 J2SE 应用程序相结合也可以单独使用。
Quartz 允许程序开发人员根据时间的间隔来调度作业。
Quartz 实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联
配置
Quartz有自己的日志输出,我们通常更喜欢log4j,所以先整合一下,整合的过程还是比较曲折的,随着版本的提高,响应的类也减少了,各个版本之间也不是那么兼容。
maven依赖:
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
log4j-slf4j
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
</dependency>
<!--这个就相当于告诉slf4j用log4j的形式输出,属于它们两者的桥梁-->
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.11.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
说明:这里的log4j2的版本要都一样,就用最新的2.11.1把,slf4j-api1.7.25 兼容了log4j2这个版本。
配置文件:
quartz.properties
org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 3
#内存存储任务,而不是数据库,一般的任务要通过数据库来实现
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
log4j2-test.properties
status = error
name = PropertiesConfig
filters = threshold
filter.threshold.type = ThresholdFilter
filter.threshold.level = debug
appenders = console
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
rootLogger.level = debug
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = STDOUT
最初学习我们不看配置,其实大概也能看懂,之后我们再查看文档就知道具体配置啥意思了。
核心部分
- Scheduler:调度器,负责作业调度的
- Job:作业接口,实现作业接口的类可以被看做是一个可以执行调度的作业
- JobDetail:为作业设定一些具体属性,比如id,描述等
- Trigger:触发器,控制作业的被调用的时机
- JobStore: 存储作业和调度期间的状态
- Calendar:指定排除的时间点(如排除法定节假日)
实例入门
job:
public class HelloJob implements Job {
public static final Logger LOGGER = LogManager.getLogger(HelloJob.class);
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
LOGGER.info("执行");
}
}
public class Main {
private static final Logger LOGGER = LogManager.getLogger(Main.class);
public static void main(String[] args) {
Scheduler scheduler = null;
try {
scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDetail job = JobBuilder.newJob(HelloJob.class)
.withIdentity("jobTest", "jobGroup")
.build();
LocalDateTime now = LocalDateTime.now();
//5秒后的时间
LocalDateTime after5s = now.plusSeconds(5);
Trigger trigger = TriggerBuilder.newTrigger()
.withDescription("5秒后启动Hello")
.withIdentity("trigger", "triggerGroup")
.startAt(DateUtils.localDateTime2Date(after5s))
//定制计划,这里是每2秒进行一次,有点像linux cron周期任务这里是 秒 分 时 日 月 周 年
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
.build();
//进行注册任务
scheduler.scheduleJob(job, trigger);
//执行
scheduler.start();
/*scheduler.shutdown();*/
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出:
2018-09-10 16:03:00 INFO HelloJob:15 - 执行
2018-09-10 16:03:02 DEBUG PropertySettingJobFactory:51 - Producing instance of Job 'jobGroup.jobTest', class=job.HelloJob
2018-09-10 16:03:02 DEBUG QuartzSchedulerThread:291 - batch acquisition of 1 triggers
2018-09-10 16:03:02 DEBUG JobRunShell:201 - Calling execute on job jobGroup.jobTest
2018-09-10 16:03:02 INFO HelloJob:15 - 执行
2018-09-10 16:03:04 DEBUG PropertySettingJobFactory:51 - Producing instance of Job 'jobGroup.jobTest', class=job.HelloJob
2018-09-10 16:03:04 DEBUG QuartzSchedulerThread:291 - batch acquisition of 1 triggers
2018-09-10 16:03:04 DEBUG JobRunShell:201 - Calling execute on job jobGroup.jobTest
2018-09-10 16:03:04 INFO HelloJob:15 - 执行
由于jdk8,LocalDate很好用而Quartz框架是用的Date,所以我自己编写了一个工具做了转换,Date和LocalDate转换就是Instant和Zone的应用,如下:
public class DateUtils {
public static LocalDate date2localDate(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
public static LocalDateTime date2localDatetime(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}
public static Date localDate2Date(LocalDate date) {
return Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
public static Date localDateTime2Date(LocalDateTime dateTime) {
return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
}
}
如何使用cron表达式 可以参照它:https://blog.csdn.net/liupeifeng3514/article/details/79469887 这样我们的一个简单的定时任务就完成了。还是挺简单的。配置完成后就可以开始使用了,当然这还是它比较简单的一点,不过不急,我们一点点地去揭开它的面纱