一、基本概念

Quartz核心的概念:scheduler任务调度、Job任务、Trigger触发器、JobDetail任务细节。

scheduler任务调度:
  是最核心的概念,需要把JobDetail和Trigger注册到scheduler中,才可以执行。
Job任务:
  其实Job是接口,其中只有一个execute方法:

Trigger触发器 

  a)作用:它是来执行工作任务,在什么条件下触发,什么时间执行,多久执行一次。

  b)四大类型:SimpleTrigger,CronTirgger,DateIntervalTrigger, 和 NthIncludedDayTrigger。

  SimpleTrigger 一般用于实现每隔一定时间执行任务,以及重复多少次,如每 2 小时执行一次,重复执行 5 次。SimpleTrigger 内部实现机制是通过计算间隔时间来计算下次的执行时间,这就导致其不适合调度定时的任务。例如我们想每天的 1:00AM 执行任务,如果使用 SimpleTrigger 的话间隔时间就是一天。注意这里就会有一个问题,即当有 misfired 的任务并且恢复执行时,该执行时间是随机的(取决于何时执行 misfired 的任务,例如某天的 3:00PM)。这会导致之后每天的执行时间都会变成 3:00PM,而不是我们原来期望的 1:00AM。

  CronTirgger 类似于 LINUX 上的任务调度命令 crontab,即利用一个包含 7 个字段的表达式来表示时间调度方式。例如,"0 15 10 * * ? *" 表示每天的 10:15AM 执行任务。对于涉及到星期和月份的调度,CronTirgger 是最适合的,甚至某些情况下是唯一选择。例如,"0 10 14 ? 3 WED" 表示三月份的每个星期三的下午 14:10PM 执行任务。读者可以在具体用到该 trigger 时再详细了解每个字段的含义。

二、详细实现案例

1、首先要在mysql里面建一个数据库,这里起名:quartz_test,并导入以下sql内容

以下的sql为实现quartz集群必须要的表,quartz集群就是通过共享一个数据库来实现的,不像redis那样的集群,节点与节点需要通信;quartz集群的节点之间是不需要通信的。

DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS; CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(120) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR(1) NULL,
BOOL_PROP_2 VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB; CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB; CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB; CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB; CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB; CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP); CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP); commit;

2、创建maven项目,完整的工程结构如下图

3、引入springboot和quartz的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.springquartz.demo</groupId>
<artifactId>spring-quartz</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<!--spring quartz依赖-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
</dependencies>
</project>

注意:以上的依赖一个都不能少,少一个都运行不起来

4、添加application.yml(不是必须的),quartz.properties文件(必须要的

application.yml

server:
port: 8084
context-path: /spring-quartz

quartz.properties

# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
# #默认或是自己改名字都行
org.quartz.scheduler.instanceName: DefaultQuartzScheduler #如果使用集群,instanceId必须唯一,设置成AUTO
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000 #============================================================================
# Configure JobStore
#============================================================================
#
#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
#存储方式使用JobStoreTX,也就是数据库
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#使用自己的配置文件
org.quartz.jobStore.useProperties:true
#数据库中quartz表的表名前缀
org.quartz.jobStore.tablePrefix:QRTZ_
org.quartz.jobStore.dataSource:qzDS
#是否使用集群(如果项目只部署到 一台服务器,就不用了)
org.quartz.jobStore.isClustered = true #============================================================================
# Configure Datasources
#============================================================================
#配置数据源
org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL:jdbc:mysql://172.16.0.151:3306/quartz_test?useUnicode=true&characterEncoding=utf8
org.quartz.dataSource.qzDS.user:root
org.quartz.dataSource.qzDS.password:huacloudhuacloud
org.quartz.dataSource.qzDS.validationQuery=select 0 from dual

注意:如果部署的是quartz集群,必须加上以上红色加粗的部分,如果只是单节点quartz可以不用加。

5、添加springboot启动类

package com.springquartz;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan; /**
* @author hzb
* @date 2018/08/18
*/
@SpringBootApplication
@ComponentScan(basePackages = { "com.springquartz" })
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}

6、创建job 实例工厂,解决spring注入问题,如果使用默认会导致spring的@Autowired 无法注入问题(很重要

package com.springquartz.factory;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import org.springframework.stereotype.Component; @Component
public class MyJobFactory extends SpringBeanJobFactory implements ApplicationContextAware { private transient AutowireCapableBeanFactory beanFactory; @Override
public void setApplicationContext(final ApplicationContext context) {
beanFactory = context.getAutowireCapableBeanFactory();
} @Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
} }

7、quartz的初始化配置

package com.springquartz.config;

import com.springquartz.factory.MyJobFactory;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean; import java.io.IOException;
import java.util.Properties; /**
* @author hzb
* @date 2018/08/28
*/
@Configuration
public class SchedulerConfiguration { @Autowired
private MyJobFactory myJobFactory; @Bean(name = "schedulerFactoryBean")
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
//获取配置属性
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("quartz.properties"));
//在quartz.properties中的属性被读取并注入后再初始化对象
propertiesFactoryBean.afterPropertiesSet();
//创建SchedulerFactoryBean
SchedulerFactoryBean factory = new SchedulerFactoryBean();
Properties pro = propertiesFactoryBean.getObject();
factory.setOverwriteExistingJobs(true);
factory.setAutoStartup(true);
factory.setQuartzProperties(pro);
factory.setJobFactory(myJobFactory);
return factory;
} }

8、新建service接口和实现类

package com.springquartz.service;

/**
* @author hzb
* @date 2018/08/28
*/
public interface JobService {
/**
* 添加一个定时任务
* @param jobName
* @param jobGroup
*/
void addCronJob(String jobName, String jobGroup); /**
* 添加异步任务
* @param jobName
* @param jobGroup
*/
void addAsyncJob(String jobName, String jobGroup); /**
* 暂停任务
* @param jobName
* @param jobGroup
*/
void pauseJob(String jobName, String jobGroup); /**
* 恢复任务
* @param triggerName
* @param triggerGroup
*/
void resumeJob(String triggerName, String triggerGroup); /**
* 删除job
* @param jobName
* @param jobGroup
*/
void deleteJob(String jobName, String jobGroup); }
package com.springquartz.service;

import com.springquartz.job.AsyncJob;
import com.springquartz.job.CronJob;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; /**
* @author hzb
* @date 2018/08/28
*/
@Service
public class JobServiceImpl implements JobService { @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
@Autowired
private SchedulerFactoryBean schedulerFactoryBean; /**
* 创建一个定时任务
*
* @param jobName
* @param jobGroup
*/
@Override
public void addCronJob(String jobName, String jobGroup) {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail != null) {
System.out.println("job:" + jobName + " 已存在");
} else {
//构建job信息
jobDetail = JobBuilder.newJob(CronJob.class).withIdentity(jobName, jobGroup).build();
//用JopDataMap来传递数据
jobDetail.getJobDataMap().put("taskData", "hzb-cron-001"); //表达式调度构建器(即任务执行的时间,每5秒执行一次)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("*/5 * * * * ?"); //按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName + "_trigger", jobGroup + "_trigger")
.withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
}
} catch (Exception e) {
e.printStackTrace();
}
} @Override
public void addAsyncJob(String jobName, String jobGroup) {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail != null) {
System.out.println("job:" + jobName + " 已存在");
}
else {
//构建job信息,在用JobBuilder创建JobDetail的时候,有一个storeDurably()方法,可以在没有触发器指向任务的时候,将任务保存在队列中了。然后就能手动触发了
jobDetail = JobBuilder.newJob(AsyncJob.class).withIdentity(jobName, jobGroup).storeDurably().build();
jobDetail.getJobDataMap().put("asyncData","this is a async task");
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName + "_trigger", jobGroup + "_trigger") //定义name/group
.startNow()//一旦加入scheduler,立即生效
.withSchedule(simpleSchedule())//使用SimpleTrigger
.build();
scheduler.scheduleJob(jobDetail, trigger);
}
} catch (Exception e) {
e.printStackTrace();
} } @Override
public void pauseJob(String jobName, String jobGroup) {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(jobName + "_trigger", jobGroup + "_trigger"); scheduler.pauseTrigger(triggerKey);
System.out.println("=========================pause job:" + jobName + " success========================");
} catch (SchedulerException e) {
e.printStackTrace();
}
} /**
* 恢复任务
*
* @param jobName
* @param jobGroup
*/
@Override
public void resumeJob(String jobName, String jobGroup) {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(jobName + "_trigger", jobGroup + "_trigger");
scheduler.resumeTrigger(triggerKey);
System.out.println("=========================resume job:" + jobName + " success========================");
} catch (SchedulerException e) {
e.printStackTrace();
}
} @Override
public void deleteJob(String jobName, String jobGroup) {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
JobKey jobKey = JobKey.jobKey(jobName,jobGroup);
scheduler.deleteJob(jobKey);
System.out.println("=========================delete job:" + jobName + " success========================");
} catch (SchedulerException e) {
e.printStackTrace();
} }
}

9、新建controller

package com.springquartz.controller;

import com.springquartz.service.JobService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; /**
* @author hzb
* @date 2018/08/28
*/
@RestController
@RequestMapping("/quartztest")
public class JobController {
@Autowired
private JobService jobService; /**
* 创建cron任务
* @param jobName
* @param jobGroup
* @return
*/
@RequestMapping(value = "/cron",method = RequestMethod.POST)
public String startCronJob(@RequestParam("jobName") String jobName, @RequestParam("jobGroup") String jobGroup){
jobService.addCronJob(jobName,jobGroup);
return "create cron task success";
} /**
* 创建异步任务
* @param jobName
* @param jobGroup
* @return
*/
@RequestMapping(value = "/async",method = RequestMethod.POST)
public String startAsyncJob(@RequestParam("jobName") String jobName, @RequestParam("jobGroup") String jobGroup){
jobService.addAsyncJob(jobName,jobGroup);
return "create async task success";
} /**
* 暂停任务
* @param jobName
* @param jobGroup
* @return
*/
@RequestMapping(value = "/pause",method = RequestMethod.POST)
public String pauseJob(@RequestParam("jobName") String jobName, @RequestParam("jobGroup") String jobGroup){
jobService.pauseJob(jobName,jobGroup);
return "pause job success";
} /**
* 恢复任务
* @param jobName
* @param jobGroup
* @return
*/
@RequestMapping(value = "/resume",method = RequestMethod.POST)
public String resumeJob(@RequestParam("jobName") String jobName, @RequestParam("jobGroup") String jobGroup){
jobService.resumeJob(jobName,jobGroup);
return "resume job success";
} /**
* 删除务
* @param jobName
* @param jobGroup
* @return
*/
@RequestMapping(value = "/delete",method = RequestMethod.PUT)
public String deleteJob(@RequestParam("jobName") String jobName, @RequestParam("jobGroup") String jobGroup){
jobService.deleteJob(jobName,jobGroup);
return "delete job success";
}
}

10、新建job,这里的job仅仅只是打印信息,不做复杂的业务

package com.springquartz.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; /**
* @author hzb
* @date 2018/08/28
*/
public class CronJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("=========================定时任务每5秒执行一次===============================");
System.out.println("jobName=====:"+jobExecutionContext.getJobDetail().getKey().getName());
System.out.println("jobGroup=====:"+jobExecutionContext.getJobDetail().getKey().getGroup());
System.out.println("taskData=====:"+jobExecutionContext.getJobDetail().getJobDataMap().get("taskData"));
}
}
package com.springquartz.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; /**
* @author Administrator
* @date 2018/08/28
*/
public class AsyncJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("========================立即执行的任务,只执行一次===============================");
System.out.println("jobName=====:"+jobExecutionContext.getJobDetail().getKey().getName());
System.out.println("jobGroup=====:"+jobExecutionContext.getJobDetail().getKey().getGroup());
System.out.println("taskData=====:"+jobExecutionContext.getJobDetail().getJobDataMap().get("asyncData"));
}
}

11、执行结果

启动程序之后,这里用postman进行测试

a、创建一个cron任务

控制台打印:

2018-08-29 14:22:11.668  INFO 3284 --- [nio-8084-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 19 ms
=========================定时任务每5秒执行一次===============================
jobName=====:cron1
jobGroup=====:cron-group1
taskData=====:hzb-cron-001
=========================定时任务每5秒执行一次===============================
jobName=====:cron1
jobGroup=====:cron-group1
taskData=====:hzb-cron-001
=========================定时任务每5秒执行一次===============================
jobName=====:cron1
jobGroup=====:cron-group1
taskData=====:hzb-cron-001
=========================定时任务每5秒执行一次===============================

b、暂停任务

控制台打印:

=========================定时任务每5秒执行一次===============================
jobName=====:cron1
jobGroup=====:cron-group1
taskData=====:hzb-cron-001
=========================定时任务每5秒执行一次===============================
jobName=====:cron1
jobGroup=====:cron-group1
taskData=====:hzb-cron-001
=========================pause job:cron1 success========================

可以看到刚才的5秒一次的定时任务不执行了

c、恢复任务

控制台打印:

=========================pause job:cron1 success========================
=========================resume job:cron1 success========================
=========================定时任务每5秒执行一次===============================
jobName=====:cron1
jobGroup=====:cron-group1
taskData=====:hzb-cron-001
=========================定时任务每5秒执行一次===============================
jobName=====:cron1
jobGroup=====:cron-group1
taskData=====:hzb-cron-001

d、删除任务

控制台打印:

=========================定时任务每5秒执行一次===============================
jobName=====:cron1
jobGroup=====:cron-group1
taskData=====:hzb-cron-001
=========================定时任务每5秒执行一次===============================
jobName=====:cron1
jobGroup=====:cron-group1
taskData=====:hzb-cron-001
=========================delete job:cron1 success========================

二、扩展:cron表达式

cron表达式用于配置cronTrigger的实例。cron表达式实际上是由七个子表达式组成。这些表达式之间用空格分隔。

1.Seconds (秒)
2.Minutes(分)
3.Hours(小时)
4.Day-of-Month  (天)
5.Month(月)
6.Day-of-Week (周)
7.Year(年)

例:"0 0 12 ? * WED” 意思是:每个星期三的中午12点执行。

个别子表达式可以包含范围或者列表。例如:上面例子中的WED可以换成"MON-FRI","MON,WED,FRI",甚至"MON-WED,SAT"。

子表达式范围:
1.Seconds (0~59)
2.Minutes (0~59)
3.Hours (0~23)
4.Day-of-Month (1~31,但是要注意有些月份没有31天)
5.Month (0~11,或者"JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV,DEC")
6.Day-of-Week (1~7,1=SUN 或者"SUN, MON, TUE, WED, THU, FRI, SAT”)
7.Year (1970~2099)

Cron表达式的格式:秒 分 时 日 月 周 年(可选)。
字段名              允许的值                    允许的特殊字符 
秒                     0-59                           , - * / 
分                     0-59                           , - * / 
小时                  0-23                           , - * / 
日                     1-31                            , - * ? / L W C
月                     1-12 or JAN-DEC        , - * / 
周几                  1-7 or SUN-SAT         , - * ? / L C # 
年(可选字段)     empty                         1970-2099 , - * /

字符含义:

:代表所有可能的值。因此,“*”在Month中表示每个月,在Day-of-Month中表示每天,在Hours表示每小时

:表示指定范围。

:表示列出枚举值。例如:在Minutes子表达式中,“5,20”表示在5分钟和20分钟触发。

:被用于指定增量。例如:在Minutes子表达式中,“0/15”表示从0分钟开始,每15分钟执行一次。"3/20"表示从第三分钟开始,每20分钟执行一次。和"3,23,43"(表示第3,23,43分钟触发)的含义一样。

:用在Day-of-Month和Day-of-Week中,指“没有具体的值”。当两个子表达式其中一个被指定了值以后,为了避免冲突,需要将另外一个的值设为“?”。例如:想在每月20日触发调度,不管20号是星期几,只能用如下写法:0 0 0 20 * ?,其中最后以为只能用“?”,而不能用“*”。

L :用在day-of-month和day-of-week字串中。它是单词“last”的缩写。它在两个子表达式中的含义是不同的。
在day-of-month中,“L”表示一个月的最后一天,一月31号,3月30号。
在day-of-week中,“L”表示一个星期的最后一天,也就是“7”或者“SAT”
如果“L”前有具体内容,它就有其他的含义了。例如:“6L”表示这个月的倒数第六天。“FRIL”表示这个月的最后一个星期五。
注意:在使用“L”参数时,不要指定列表或者范围,这样会出现问题。

W :“Weekday”的缩写。只能用在day-of-month字段。用来描叙最接近指定天的工作日(周一到周五)。例如:在day-of-month字段用“15W”指“最接近这个月第15天的工作日”,即如果这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;如果这个月第15天是周日,那么触发器将会在这个月第 16天即周一触发;如果这个月第15天是周二,那么就在触发器这天触发。注意一点:这个用法只会在当前月计算值,不会越过当前月。“W”字符仅能在 day-of-month指明一天,不能是一个范围或列表。也可以用“LW”来指定这个月的最后一个工作日,即最后一个星期五。

# :只能用在day-of-week字段。用来指定这个月的第几个周几。例:在day-of-week字段用"6#3" or "FRI#3"指这个月第3个周五(6指周五,3指第3个)。如果指定的日期不存在,触发器就不会触发。

表达式例子:

0 * * * * ? 每1分钟触发一次
0 0 * * * ? 每天每1小时触发一次
0 0 10 * * ? 每天10点触发一次
0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发 
0 30 9 1 * ? 每月1号上午9点半
0 15 10 15 * ? 每月15日上午10:15触发

*/5 * * * * ? 每隔5秒执行一次
0 */1 * * * ? 每隔1分钟执行一次
0 0 5-15 * * ? 每天5-15点整点触发
0 0/3 * * * ? 每三分钟触发一次
0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发 
0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点

0 0 12 ? * WED 表示每个星期三中午12点
0 0 17 ? * TUES,THUR,SAT 每周二、四、六下午五点
0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发 
0 15 10 ? * MON-FRI 周一至周五的上午10:15触发

0 0 23 L * ? 每月最后一天23点执行一次
0 15 10 L * ? 每月最后一日的上午10:15触发 
0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发

0 15 10 * * ? 2005 2005年的每天上午10:15触发 
0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发 
0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发

springboot+mysql实现quartz集群搭建的更多相关文章

  1. Linux下MySQL/MariaDB Galera集群搭建过程【转】

    MariaDB介绍 MariaDB是开源社区维护的一个MySQL分支,由MySQL的创始人Michael Widenius主导开发,采用GPL授权许可证. MariaDB的目的是完全兼容MySQL,包 ...

  2. MySQL优化之——集群搭建步骤具体解释

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46833179 1 概述 MySQL Cluster 是MySQL 适合于分布式计算 ...

  3. MySQL之PXC集群搭建

    一.PXC 介绍 1.1 PXC 简介 PXC 是一套 MySQL 高可用集群解决方案,与传统的基于主从复制模式的集群架构相比 PXC 最突出特点就是解决了诟病已久的数据复制延迟问题,基本上可以达到实 ...

  4. Mysql Innodb cluster集群搭建

    之前搭建过一个Mysql Ndb cluster集群,但是mysql版本是5.7的,看到官网上mysql8的还是开发者版本,所以尝试搭建下mysql Innodb cluster集群. MySQL的高 ...

  5. Linux下MySQL/MariaDB Galera集群搭建过程

    MariaDB介绍 MariaDB是开源社区维护的一个MySQL分支,由MySQL的创始人Michael Widenius主导开发,采用GPL授权许可证. MariaDB的目的是完全兼容MySQL,包 ...

  6. 转mysql复制主从集群搭建

    最近搭了个主从复制,中间出了点小问题,排查搞定,记录下来 1环境:虚拟机:OS:centos6.5Linux host2 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 ...

  7. 使用sqlserver搭建高可用双机热备的Quartz集群部署【附源码】

    一般拿Timer和Quartz相比较的,简直就是对Quartz的侮辱,两者的功能根本就不在一个层级上,如本篇介绍的Quartz强大的序列化机制,可以序列到 sqlserver,mysql,当然还可以在 ...

  8. Springboot quartz集群(3) — 多节点发送邮件

    本期将提供quartz集群能力 集群案例分析: 上一期的邮件发送功能,若在服务需要部署多节点,但定时任务不支持集群,因此,多节点定时任务势必会同时运行, 若向用户发送邮件通知,这种情况下会向用户发送两 ...

  9. 【Data Cluster】真机环境下MySQL数据库集群搭建

    真机环境下MySQL-Cluster搭建文档  摘要:本年伊始阶段,由于实验室对不同数据库性能测试需求,才出现MySQL集群搭建.购置主机,交换机,双绞线等一系列准备工作就绪,也就开始集群搭建.起初笔 ...

随机推荐

  1. f5基本介绍

    1.信息查看 1)登录: https://10.160.100.10 f5有2台,做HA IP地址分别为10.160.100.3和10.160.100.2 10.160.100.10为虚拟地址 2)基 ...

  2. ztree-持续更新中

    版本v3快速入门: 1,官网下载https://gitee.com/zTree/zTree_v3 2,zTree-zTree_v3-master\zTree_v3下复制css和js文件夹到项目下 3, ...

  3. akuna capital oa

    记得截图没过的test case啊!否则连复习改bug的证据都没了啊!!! 其实也不一定非得要拿面试来测试,做做lc的contest,看看自己哪里不会,也是一样的效果. 注意是单选题还是多选题 has ...

  4. 纯css实现div中未知尺寸图片的垂直居中

    1.淘宝的方法 在曾经的"淘宝UED招聘"中有这样一道题目: “使用纯CSS实现未知尺寸的图片(但高宽都小于200px)在200px的正方形容器中水平和垂直居中.” 当然出题并不是 ...

  5. 线特征---LineMatching原理(四)

    参考文章:An efficient and robust line segment matching approach based on LBD descriptor and pairwise geo ...

  6. odroid xu4

    1, sd 2, flashing image 3, GParted 4, ROS install 5, make an image sudo dd if=/dev/sdb of=~/odroid/o ...

  7. 开启Windows文件共享必须开启的两个服务

    开启Windows文件共享必须开启的两个服务分别是: 1.Server服务. 2.Workstation服务. 如果文件共享丢失,可以去首先去查看这两个服务是否停止,如果停止,请启动或者重启.

  8. mysql 添加外键

    create table class( cid tinyint unsigned primary key auto_increment, caption varchar(15) not null)en ...

  9. c#devexpres窗体划分 以及panelcontrol 相关操作

    想模仿flashfxp  做一个svn上传的客户端 左侧为本地目录,右侧为svn服务器目录 准备用devexpress 的 控件实现,顺便练习一下devexpress 相关使用. 1:要实现菜单栏工具 ...

  10. BZOJ1217或洛谷2279 [HNOI2003]消防局的设立

    BZOJ原题链接 洛谷原题链接 该题有两种做法,树形\(DP\)和贪心. 先讲贪心. 先将所有点按深度从大到小排序,然后从大到小依次取出点,若已经被覆盖则跳过,否则就在它的祖父点建立消防站. 考虑如何 ...