欢迎大家关注我的公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。
一、Quartz
1、简介
起初是OpenSymphony组织提供的一个功能丰富的开源作业调度框架
官网:http://www.quartz-scheduler.org/
纯java编写,用法简单而功能强大。
2、特点
- 强大的作业调度功能
作为spring默认的调度框架,极易与spring无缝整合,实现灵活可配置的调度功能,quartz提供了调 度运行环境持久化机制,可以保存并恢复调度现场,即使系统因故障关闭也不会造成调度现场的数据丢失。 - 灵活的应用方式
允许我们灵活定义触发器的调度时间规则,并可以将触发器与任务进行关联绑定,quartz提供了主键式的监听器,各种插件以及线程池等功能,支持任务和调度的多重组合,支持调度数据的多种存储方式。 - 分布式和集群能力
Quartz 集群中的每个节点是一个独立的 Quartz 应用,需要对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与其他的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。
3、核心结构
- job(或task)是实现定时功能的接口:如定时推送消息等。
- trigger是触发执行定时任务的触发器,基本设置有:指定job的运行时间,时间间隔,运行次数等。
- schedule是调度指定的trigger去执行指定的job。
二、集成Quartz
1、集成quartz的两种方式说明
spring使用quartz大致有2种方式:一是任务类继承QuartzJobBean,二是在xml文件里定义任务类和要执行的方法,为了简化配置和快速开发,一般使用第一种较多。
2、pom.xml引入相关依赖
<!--定时任务quartz-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
3、定义任务类
继承QuartzJobBean,重写excuteInternal方法
package com.riemann.springbootdemo.service.impl;
import com.riemann.springbootdemo.model.EmailMessage;
import com.riemann.springbootdemo.service.MailService;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author riemann
* @date 2019/06/23 18:15
*/
@Component
public class EmailTask extends QuartzJobBean {
private static final Logger logger = LoggerFactory.getLogger(EmailTask.class);
@Autowired
private MailService mailService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
EmailMessage message = new EmailMessage();
message.setMessageCode("MissingParameter");
message.setMessageStatus("Failed");
message.setCause("缺少参数,请确认");
// 这里写调用执行定时调度任务的逻辑
mailService.sendMessageMail(message, "测试消息通知", "emailMessage.html");
logger.info("------定时任务成功 EmailTask: ------" + new Date());
}
}
4、定义配置类
在配置类中定义JobDetail和SimpleTrigger。
package com.riemann.springbootdemo.util.configuration;
import com.riemann.springbootdemo.service.impl.EmailTask;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author riemann
* @date 2019/06/23 18:21
*/
@Configuration
public class TaskConfig {
// 定义要执行的EmailTask任务类
@Bean
public JobDetail emailJobDetail() {
return JobBuilder.newJob(EmailTask.class).withIdentity("emailJob").storeDurably().build();
}
// Simple触发器定义与设置
@Bean
public SimpleTrigger emailJobDetailTrigger() {
// Simple类型:可设置时间间隔、是否重复、触发频率(misfire机制)等
// 这里我设置的10s的定时任务
SimpleScheduleBuilder ssb = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10).repeatForever();
// 一个Trigger只对应一个Job,Schedule调度器调度Trigger执行对应的Job
SimpleTrigger sTrigger = TriggerBuilder.newTrigger().forJob(emailJobDetail()).
withIdentity("sampleTrigger").withDescription("simple类型的触发器").withSchedule(ssb).build();
return sTrigger;
}
}
当然,上面是一个简单的触发器SimpleTrigger ,经常使用的还有CronTrigger。
// Cron触发器定义与设置
@Bean
public CronTrigger emailTaskyCronTrigger() {
// Cron类型:通过cron表达式设置触发规则
CronScheduleBuilder csb = CronScheduleBuilder.cronSchedule(String.format("0 */1 * * * ?"))
.withMisfireHandlingInstructionDoNothing();
// 一个Trigger只对应一个Job,Schedule调度器调度Trigger执行对应的Job
CronTrigger cTrigger = TriggerBuilder.newTrigger().forJob(emailJobDetail()).
withIdentity("emailTaskCronTrigger").withDescription("corn类型的触发器").withSchedule(csb).startNow().build();
return cTrigger;
}
三、测试
启动SpringBootDemoApplication,观察控制台输出
SimpleTrigger设置的是10秒执行一次:
CronTrigger设置的是一分钟执行一次:
四、总结
集成quartz和使用它是很简单的,抓住Job,Trigger,Schedule三大核心对象就可以玩转quartz了。
另外corn表达式也是经常会用的一个点,有关corn的组成规则,线上验证工具可以参考下面的路径:
在线生成corn表达式工具:http://cron.qqe2.com/