plugins {
id 'org.springframework.boot' version '2.2.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.learn'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenLocal()
maven { url "http://maven.aliyun.com/nexus/content/groups/public/"}
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-quartz'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
compile group: 'com.mchange', name: 'c3p0', version: '0.9.5.2'
}
test {
useJUnitPlatform()
}
在quartz官网下载的压缩包docs/dbTables中可找到
#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#
#
# By: Ron Cordell - roncordell
# I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
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;
-- ----------------------------
-- Table structure for quartz_task
-- ----------------------------
DROP TABLE IF EXISTS `quartz_task`;
CREATE TABLE `quartz_task` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`task_name` varchar(255) DEFAULT NULL COMMENT '任务名称',
`group_name` varchar(255) DEFAULT NULL COMMENT 'group名称',
`job_class` varchar(255) DEFAULT NULL COMMENT 'job所在类',
`params` varchar(255) DEFAULT NULL COMMENT '参数',
`cron` varchar(255) DEFAULT NULL COMMENT 'cron表达式',
`status` tinyint(1) DEFAULT NULL COMMENT '状态',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of quartz_task
-- ----------------------------
INSERT INTO `quartz_task` VALUES ('1', 'job1', 'group1', 'com.learn.quartz.job.ScheduledTask01', '参数1', '0 1/2 * * * ?', '1');
INSERT INTO `quartz_task` VALUES ('2', 'job2', 'group2', 'com.learn.quartz.job.ScheduledTask02', '参数2', '0 0/2 * * * ?', '1');
INSERT INTO `quartz_task` VALUES ('3', 'job3', 'group3', 'com.learn.quartz.job.ScheduledTask03', '参数3', '0 0/1 * * * ?', '0');
SchedulerFactoryBean将会通过QuartzAutoConfiguration类自动生成实例,Scheduler也自动生成实例,其中jobFactory默认注入SpringBeanJobFactory(SpringBeanJobFactory支持Job实现类中Service Autowire注入和JobDataMap中的数据以setter方法注入),数据库连接池默认使用c3p0
server.port=8080
#数据库
spring.datasource.url=jdbc:mysql://xxxxxxxxxx
spring.datasource.username=root
spring.datasource.password=xxxxxxxx
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#mapper
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.configuration.map-underscore-to-camel-case=true
logging.level.root=info
# ===========================================================================
# SchedulerFactoryBean基本配置
# ===========================================================================
#启动延迟n秒
spring.quartz.startup-delay=1
#是否重写已存在的job
spring.quartz.overwrite-existing-jobs=true
#是否自动启动
spring.quartz.auto-startup=true
#quartz集群配置
# ===========================================================================
# Configure Main Scheduler Properties 调度器属性
# ===========================================================================
#调度标识名 集群中每一个实例都必须使用相同的名称
spring.quartz.properties.org.quartz.scheduler.instanceName = DefaultQuartzScheduler
#ID设置为自动获取 每一个必须不同
spring.quartz.properties.org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
#线程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
spring.quartz.properties.org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#指定线程数,至少为1(无默认值)(一般设置为1-100直接的整数合适)
spring.quartz.properties.org.quartz.threadPool.threadCount = 25
#设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
spring.quartz.properties.org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
# 触发失败阈值,未超过触发时间60s则直接触发,若超过则失火,log信息Handling 1 trigger(s) that missed their scheduled fire-time.
spring.quartz.properties.org.quartz.jobStore.misfireThreshold = 60000
#数据保存方式为数据库持久化
spring.quartz.properties.org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#JobDataMaps是否都为String类型
spring.quartz.properties.org.quartz.jobStore.useProperties = false
#表的前缀,默认QRTZ_
spring.quartz.properties.org.quartz.jobStore.tablePrefix = QRTZ_
#是否加入集群
spring.quartz.properties.org.quartz.jobStore.isClustered = true
#调度实例失效的检查时间间隔
spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval = 20000
#名称必须与下方org.quartz.dataSource.@[email protected]一致
spring.quartz.properties.org.quartz.jobStore.dataSource = myDS
#============================================================================
# Configure Datasources
#============================================================================
#数据库引擎
spring.quartz.properties.org.quartz.dataSource.myDS.driver = com.mysql.cj.jdbc.Driver
#数据库连接
spring.quartz.properties.org.quartz.dataSource.myDS.URL = jdbc:mysql://xxxxxxxxxx
#数据库用户
spring.quartz.properties.org.quartz.dataSource.myDS.user = root
#数据库密码
spring.quartz.properties.org.quartz.dataSource.myDS.password = xxxxxx
#允许最大连接
spring.quartz.properties.org.quartz.dataSource.myDS.maxConnections = 5
#验证查询sql,可以不设置
spring.quartz.properties.org.quartz.dataSource.myDS.validationQuery=select 0 from dual
SchedulerFactoryBean 数据源使用spring项目自动生成的,配置文件中不用另配Datasources设置,可设置事务管理(第一种貌似没?)
server.port=8080
#数据库
spring.datasource.url=jdbc:mysql://xxxxxxxxxx
spring.datasource.username=root
spring.datasource.password=xxxxxxxx
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#mapper
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.configuration.map-underscore-to-camel-case=true
logging.level.root=info
# ===========================================================================
# Configure Main Scheduler Properties 调度器属性
# ===========================================================================
#调度标识名 集群中每一个实例都必须使用相同的名称
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
#ID设置为自动获取 每一个必须不同
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
#线程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#指定线程数,至少为1(无默认值)(一般设置为1-100直接的整数合适)
org.quartz.threadPool.threadCount = 25
#设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
# 触发失败阈值,未超过触发时间60s则直接触发,若超过则失火,log信息Handling 1 trigger(s) that missed their scheduled fire-time.
org.quartz.jobStore.misfireThreshold = 60000
#数据保存方式为数据库持久化
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#JobDataMaps是否都为String类型
org.quartz.jobStore.useProperties = false
#表的前缀,默认QRTZ_
org.quartz.jobStore.tablePrefix = QRTZ_
#是否加入集群
org.quartz.jobStore.isClustered = true
#调度实例失效的检查时间间隔
org.quartz.jobStore.clusterCheckinInterval = 20000
@Configuration
public class QuartzConfigurer {
@Autowired
private DataSource dataSource;
@Autowired
private PlatformTransactionManager txManager;
@Bean(name = "quartzScheduler")
public SchedulerFactoryBean quartzScheduler() throws IOException {
//创建SchedulerFactoryBean
SchedulerFactoryBean factory = new SchedulerFactoryBean();
//设置调度器自动运行
factory.setAutoStartup(true);
//设置配置文件位置
factory.setConfigLocation(new ClassPathResource("/quartz.properties"));
//设置job工厂,使job可以自动注入
SpringBeanJobFactory jobFactory = new SpringBeanJobFactory();
factory.setJobFactory(jobFactory);
//设置数据源
factory.setDataSource(dataSource);
//设置事务
factory.setTransactionManager(txManager);
//设置重写已存在的Job
factory.setOverwriteExistingJobs(true);
return factory;
}
@Bean(name = "scheduler")
public Scheduler scheduler() throws IOException {
return quartzScheduler().getScheduler();
}
}
自建表quart_task的实体类
@Setter
@Getter
@ToString
public class QuartzTask implements Serializable {
private static final long serialVersionUID = 2605762417952271886L;
/**
* 主键
*/
private Integer id;
/**
* 任务名称
*/
private String taskName;
/**
* group名称
*/
private String groupName;
/**
* job所在类
*/
private String jobClass;
/**
* 参数
*/
private String params;
/**
* cron表达式
*/
private String cron;
/**
* 状态
*/
private Boolean status;
}
自建表quart_task的mapper
public interface QuartzTaskMapper {
QuartzTask selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(QuartzTask record);
List<QuartzTask> getAllTask();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.learn.quartz.dao.QuartzTaskMapper">
<resultMap id="BaseResultMap" type="com.learn.quartz.pojo.QuartzTask">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="task_name" jdbcType="VARCHAR" property="taskName" />
<result column="group_name" jdbcType="VARCHAR" property="groupName" />
<result column="job_class" jdbcType="VARCHAR" property="jobClass" />
<result column="params" jdbcType="VARCHAR" property="params" />
<result column="cron" jdbcType="VARCHAR" property="cron" />
<result column="status" jdbcType="BIT" property="status" />
</resultMap>
<sql id="Base_Column_List">
id, task_name, group_name, job_class, params, cron, `status`
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from quartz_task
where id = #{id,jdbcType=INTEGER}
</select>
<update id="updateByPrimaryKeySelective" parameterType="com.learn.quartz.pojo.QuartzTask">
update quartz_task
<set>
<if test="taskName != null">
task_name = #{taskName,jdbcType=VARCHAR},
</if>
<if test="groupName != null">
group_name = #{groupName,jdbcType=VARCHAR},
</if>
<if test="jobClass != null">
job_class = #{jobClass,jdbcType=VARCHAR},
</if>
<if test="params != null">
params = #{params,jdbcType=VARCHAR},
</if>
<if test="cron != null">
cron = #{cron,jdbcType=VARCHAR},
</if>
<if test="status != null">
`status` = #{status,jdbcType=BIT},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<select id="getAllTask" resultType="com.learn.quartz.pojo.QuartzTask">
select
<include refid="Base_Column_List"/>
from
quartz_task
</select>
</mapper>
自建表quart_task的service
public interface QuartzTaskService {
QuartzTask selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(QuartzTask record);
List<QuartzTask> getAllTask();
}
Quartz服务层接口
public interface QuartzService {
void initAllTask(List<QuartzTask> scheduledTaskBeanList) throws Exception;
void addJob(QuartzTask scheduledTask);
void updateJob(QuartzTask quartzTask);
void deleteJob(QuartzTask quartzTask);
}
@Service
public class QuartzTaskServiceImpl implements QuartzTaskService {
@Autowired
private QuartzTaskMapper quartzTaskMapper;
@Override
public QuartzTask selectByPrimaryKey(Integer id) {
return quartzTaskMapper.selectByPrimaryKey(id);
}
@Override
public int updateByPrimaryKeySelective(QuartzTask record) {
return quartzTaskMapper.updateByPrimaryKeySelective(record);
}
@Override
public List<QuartzTask> getAllTask() {
return quartzTaskMapper.getAllTask();
}
}
Quartz服务层接口
package com.learn.quartz.service.impl;
import com.learn.quartz.pojo.QuartzTask;
import com.learn.quartz.service.QuartzService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class QuartzServiceImpl implements QuartzService {
@Autowired
private Scheduler scheduler;
/**
* 程序启动时初始化 ==> 启动所有正常状态的任务
*/
@Override
public void initAllTask(List<QuartzTask> quartzTaskList) throws Exception {
log.info("程序启动 ==> 初始化所有任务开始 !");
if (CollectionUtils.isEmpty(quartzTaskList)) {
scheduler.shutdown();
return;
}
for (QuartzTask quartzTask : quartzTaskList) {
//判断是否启动状态
if (quartzTask.getStatus()) {
this.addJob(quartzTask);
}
}
log.info("程序启动 ==> 初始化所有任务结束 !");
}
/**
* 创建job,可传参
*
* @param quartzTask 任务名称
*/
@Override
public void addJob(QuartzTask quartzTask) {
String taskName = quartzTask.getTaskName();
String groupName = quartzTask.getGroupName();
String cron = quartzTask.getCron();
TriggerKey triggerKey = TriggerKey.triggerKey(taskName, groupName);
try {
boolean result = scheduler.checkExists(triggerKey);
//job已存在,直接返回
log.info("checkExists quartTask = {} , result = {}", quartzTask, result);
if (result) {
return;
}
Class<?> aClass = Class.forName(quartzTask.getJobClass());
//构建job信息
JobDetail jobDetail = JobBuilder.newJob(((Job) aClass.newInstance()).getClass()).withIdentity(taskName, groupName).build();
//表达式调度构建器(即任务执行的时间)
/*使用withMisfireHandlingInstructionDoNothing是因为重启项目时之前添加的job都算失火
,默认配置withMisfireHandlingInstructionFireAndProceed失火后会立即执行一遍,
而withMisfireHandlingInstructionDoNothing失火后不会立即执行,而是按照下一个cron执行
*/
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron).withMisfireHandlingInstructionDoNothing();
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().startNow().withIdentity(taskName, groupName).withSchedule(scheduleBuilder).build();
//获得JobDataMap,写入数据
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("id", quartzTask.getId());
paramMap.put("params", quartzTask.getParams());
trigger.getJobDataMap().putAll(paramMap);
scheduler.scheduleJob(jobDetail, trigger);
log.info("addJob quartTask = {} is success", quartzTask);
} catch (Exception e) {
log.error("addJob quartTask = {} is fail, msg = {}", quartzTask, e);
}
}
/**
* job 更新,更新频率和参数
*
* @param quartzTask 任务名称
*/
@Override
public void updateJob(QuartzTask quartzTask) {
String taskName = quartzTask.getTaskName();
String groupName = quartzTask.getGroupName();
String cron = quartzTask.getCron();
TriggerKey triggerKey = TriggerKey.triggerKey(taskName, groupName);
try {
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (cron != null) {
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron).withMisfireHandlingInstructionDoNothing();
// 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().startNow().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
}
//获得JobDataMap,写入数据
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("id", quartzTask.getId());
paramMap.put("params", quartzTask.getParams());
trigger.getJobDataMap().putAll(paramMap);
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
log.info("updateJob quartTask = {} is success", quartzTask);
} catch (SchedulerException e) {
log.error("updateJob quartTask = {} is fail, msg = {}", quartzTask, e);
}
}
/**
* job 删除
*
* @param quartzTask 任务名称
*/
@Override
public void deleteJob(QuartzTask quartzTask) {
String taskName = quartzTask.getTaskName();
String groupName = quartzTask.getGroupName();
try {
scheduler.pauseTrigger(TriggerKey.triggerKey(taskName, groupName));
scheduler.unscheduleJob(TriggerKey.triggerKey(taskName, groupName));
scheduler.deleteJob(JobKey.jobKey(taskName, groupName));
log.info("deleteJob quartTask = {} is success", quartzTask);
} catch (SchedulerException e) {
log.error("deleteJob quartTask = {} is fail, msg = {}", quartzTask, e);
}
}
}
此类全类名必须与quart_task表中的class_name一致。
QuartzTaskService和id、params通过set方法注入(jobFactory必须注入SpringBeanJobFactory才生效)
@Slf4j
@Setter
public class ScheduledTask01 implements Job {
private QuartzTaskService quartzTaskService;
private Integer id;
private String params;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
if (quartzTaskService!=null){
QuartzTask quartzTask = quartzTaskService.selectByPrimaryKey(id);
log.info("ScheduledTask => 01 quartzTask = {}", quartzTask);
}
log.info("ScheduledTask => 01 run 当前线程名称 {}, Data = {}", Thread.currentThread().getName(), params);
}
}
项目启动后会先查询全部QuartzTask,然后status为true的持久化进job(quartz官方提供的表里 QRTZ_TRIGGERS、QRTZ_CRON_TRIGGERS、QRTZ_JOB_DETAILS),而原本就已经持久化过的无操作(重新添加已存在的job会报错)
/**
* @see @Order注解的执行优先级是按value值从小到大顺序。
* 项目启动完毕后开启需要自启的任务
*/
@Component
@Order(value = 1)
@Slf4j
public class ScheduledTaskRunner implements ApplicationRunner {
@Autowired
private QuartzTaskService quartzTaskService;
@Autowired
private QuartzService quartzService;
/**
* 程序启动完毕后,需要自启的任务
*/
@Override
public void run(ApplicationArguments args) throws Exception {
log.info(" >>>>>> 项目启动完毕, 开启 => 需要自启的任务 开始!");
List<QuartzTask> activatedTaskList = quartzTaskService.getAllTask();
quartzService.initAllTask(activatedTaskList);
log.info(" >>>>>> 项目启动完毕, 开启 => 需要自启的任务 结束!");
}
}
主要修改状态和cron
@RestController
@Slf4j
public class JobController {
@Autowired
private QuartzService quartzService;
@Autowired
private QuartzTaskService quartzTaskService;
/**
* 修改任务的cron
*
* @return
*/
@RequestMapping("/updateJobCron")
public Object updateJobCron(Integer id, String cron) {
QuartzTask quartzTask = quartzTaskService.selectByPrimaryKey(id);
Map<String, String> resultMap = new HashMap<>();
//如果存在quartzTask对象
if (quartzTask != null) {
//修改任务的cron
quartzTask.setCron(cron);
//更新quart_task
quartzTaskService.updateByPrimaryKeySelective(quartzTask);
//如果启用状态则修改当前已持久化的job
if (quartzTask.getStatus()) {
quartzService.updateJob(quartzTask);
}
resultMap.put("status", "0");
resultMap.put("msg", "修改cron成功");
return resultMap;
}
//不存在quartzTask对象
resultMap.put("status", "1");
resultMap.put("msg", "修改cron失败");
return resultMap;
}
/**
* 是否启用接口
*
* @return
*/
@RequestMapping("/updateJobStatus")
public Object updateJobStatus(Integer id, Boolean status) {
QuartzTask quartzTask = quartzTaskService.selectByPrimaryKey(id);
Map<String, String> resultMap = new HashMap<>();
if (quartzTask != null) {
//修改任务的启用状态
quartzTask.setStatus(status);
//更新quart_task
quartzTaskService.updateByPrimaryKeySelective(quartzTask);
//根据status判断是新增job还是删除job
if (status) {
quartzService.addJob(quartzTask);
} else {
quartzService.deleteJob(quartzTask);
}
resultMap.put("status", "0");
resultMap.put("msg", "修改状态成功");
return resultMap;
}
resultMap.put("status", "1");
resultMap.put("msg", "修改状态失败");
return resultMap;
}
}
最后启动项目即可