文章参考
https://blog.csdn.net/l18848956739/article/details/86597709
https://blog.csdn.net/xibei19921101/article/details/105012749
https://blog.csdn.net/WLPJLP/article/details/103908448
https://blog.csdn.net/sqlgao22/article/details/100669377
quartz
如果仅仅只是使用定时任务,可以使用spring的schedule实现,方便,代码量少.易于实现,但是,
当使用分布式进行项目部署的时候,就会出现所有的服务器都在跑同一个定时,出现一个定时任务执行多次的情况,会出现很多问题,使用quartz进行定时任务的调度就可以避免这个问题。
quartz的优点
1.可以实现多个定时任务进行调度。
2.可以实现与代码的解耦,通过配置文件的方式进行配置。
3.功能强大,可以通过cron表达式设置复杂的时间任务调度。
quartz核心:
1.job:(被任务调度的接口),我们需要实现job接口,和继承TimerTask重写run方法一样,重写job中的excute方法,excute方法是任务调度的方法执行位置。
2.JobDetail:必须通过JobDetail来实现Job实例,(基于builder模式实现的)
3.trigger(包括:CronTrigger 和simpleTrigger):指定任务调度的频率时间。何时进行任务调度(基于builder模式实现的)触发器
4.scheduler:结合jobdetail 实例和trigger实例,进行调度的触发的调度器(基于factory模式)。
Quartz 中集群如何工作
一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。离开了db将无法感知.
项目功能
1、springboot集成quartz,使用druid连接池
2、支持http请求任务定时调度,当前支持get、post 请求类型,并记录返回内容
3、通过web界面进行任务管理,包括任务暂停、恢复、修改、历史记录、历史任务查看功能
4、支持调用接口(/quartz/httpJob/add)进行任务添加
5、根据jobName或jobGroup进行查询
1.导入数据库表
因为Quartz 集群依赖于数据库,所以必须首先创建Quartz数据库表。Quartz 包括了所有被支持的数据库平台的 SQL 脚本。这是是mysql,其他数据库官网下载
注意:创建的表表名都是小写的,在代码中使用的是大写的表名;在liunx中的mysql数据库默认是大小写敏感的,因此使用liunx的数据库会出现找不到表的情况,酌情修改表或是改变数据库配置
表中所有字段详解: quartz中表及其表字段的意义_sqlgao22的博客-CSDN博客
CREATE DATABASE `quartz` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
USE quartz;
-- QUARTZ_TABLE
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;
-- quartz自带表结构
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);
-- 定时任务
DROP TABLE IF EXISTS schedule_job;
CREATE TABLE schedule_job(
ID BIGINT (50) NOT NULL AUTO_INCREMENT COMMENT '任务id',
JOB_NAME VARCHAR (100) NOT NULL COMMENT '任务名称',
JOB_GROUP VARCHAR (100) NOT NULL COMMENT '任务分组',
DESCRIPTION VARCHAR (100) NOT NULL COMMENT '任务描述',
cron_expression VARCHAR (200) NOT NULL COMMENT 'cron表达式',
TASK_STATUS VARCHAR (20) NOT NULL COMMENT '任务状态',
REQUEST_TYPE VARCHAR (50) NOT NULL COMMENT '请求类型{GET或POST请求}',
HTTP_URL VARCHAR (256) NOT NULL COMMENT '请求url',
HTTP_PARAMS VARCHAR (20000) COMMENT '请求参数',
CREATE_TIME datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
UPDATE_TIME datetime COMMENT '修改时间',
PRIMARY KEY (ID)
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '定时任务';
-- 定时任务日志
DROP TABLE IF EXISTS schedule_job_log;
CREATE TABLE schedule_job_log(
ID BIGINT (50) NOT NULL AUTO_INCREMENT COMMENT '日志id',
JOB_ID BIGINT (100) NOT NULL COMMENT '任务id',
JOB_NAME VARCHAR (100) NOT NULL COMMENT '任务名称',
JOB_GROUP VARCHAR (100) NOT NULL COMMENT '任务分组',
DESCRIPTION VARCHAR (100) COMMENT '任务描述',
cron_expression VARCHAR (100) NOT NULL COMMENT 'cron表达式',
TASK_STATUS VARCHAR (20) NOT NULL COMMENT '任务状态 0:成功,1:失败',
REQUEST_TYPE VARCHAR (50) NOT NULL COMMENT '请求类型',
HTTP_URL VARCHAR (256) NOT NULL COMMENT '请求url',
HTTP_PARAMS VARCHAR (20000) COMMENT '请求参数',
times INT (11) COMMENT '耗时(单位:毫秒)',
CREATE_TIME datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
UPDATE_TIME datetime COMMENT '修改时间',
PRIMARY KEY (ID)
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '定时任务日志表';
ALTER TABLE schedule_job ADD UNIQUE INDEX `UNIQUEIDX_SCHEDULE_JOB`(`JOB_NAME`, `JOB_GROUP`);
ALTER TABLE schedule_job_log ADD INDEX `IDX_SCHEDULE_JOB_LOG`(`JOB_NAME`, `JOB_GROUP`);
INSERT INTO `httpjob_details` VALUES ('1', 'task_ce', 'web', '测试无参数job', '* * * * * ?' , null,'POST_JSON', 'http://localhost:8080/quartz/test/job', '', '2021-09-22 10:33:00', null);
INSERT INTO `httpjob_details` VALUES ('9', 'task3', 'adce', '测试有参数job' , '* * * * * ?', '0' ,'POST_JSON', 'http://localhost:8080/quartz/test/job', ' \r\n{\r\n \"jobName\": \"task3\",\r\n \"jobGroup\": \"adce\"\r\n}', '2021-09-24 16:28:11', null);
commit;
2.引入pom依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 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>
<!--httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<!-- commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<!-- fastJson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.53</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
3.application.properties配置
server.port=8080
#UTF-8字符过滤
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
# mysql
spring.datasource.url=jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.jdbc.Driver
# druid连接池的配置信息
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
spring.datasource.maxWait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.filters=stat
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# mybatis Mapper文件
mybatis.mapper-locations=classpath*:mappings/*.xml
# mybatis别名配置
mybatis.type-aliases-package=com.example.quartz.model
引入quartz.properties配置
注意:使用分布式集群跑定时任务时,需要使用到db持久化,所以需要所有的节点共享一个数据源.
关键配置都有注释
#quartz集群配置
# ===========================================================================
# Configure Main Scheduler Properties 调度器属性
# ===========================================================================
#调度标识名 集群中每一个实例都必须使用相同的名称
org.quartz.scheduler.instanceName: MyQuartzScheduler
#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
#============================================================================
# 信息保存时间 默认值60秒,misfire任务为错过调度触发时间的任务,超过60000ms后被判定为misfire
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
#数据库别名 随便取
org.quartz.jobStore.dataSource: myDS
#表的前缀,默认QRTZ_
org.quartz.jobStore.tablePrefix: QRTZ_
#是否加入集群
org.quartz.jobStore.isClustered: true
#调度实例失效的检查时间间隔
org.quartz.jobStore.clusterCheckinInterval: 20000
#避免集群环境下job重复执行
org.quartz.jobStore.acquireTriggersWithinLock: true
4.springboot的配置类
(1)druid数据源配置类
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* druid数据源配置类
*/
@Configuration
public class DataSourceConfig {
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String userName;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.filters}")
private String filters;
@Value("{spring.datasource.connectionProperties}")
private String connectionProperties;
@Primary
@Bean
public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl);
datasource.setUsername(userName);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
//configuration
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
WallConfig wallConfig = new WallConfig();
wallConfig.setMultiStatementAllow(true);
WallFilter wallFilter= new WallFilter();
wallFilter.setConfig(wallConfig);
List<Filter> filterList = new ArrayList<>();
filterList.add(wallFilter);
datasource.setProxyFilters(filterList);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
e.printStackTrace();
}
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
}
(2)Quartz配置类
添加 QuartzConfig 类 来声明相关Bean
import com.example.quartz.job.ScheduleJob;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.Properties;
/**
* Quartz配置类
*/
@Configuration
public class QuartzConfig {
@Autowired
private DataSource dataSource;
@Autowired
private JobFactory jobFactory;
/**
* 配置quartz配置文件
*/
@Bean
public Properties properties() throws IOException {
Properties properties = new Properties();
properties.load(new ClassPathResource("/quartz.properties").getInputStream());
return properties;
}
//配置定时任务1
@Bean
public JobDetailFactoryBean job1() {
JobDetailFactoryBean jobDetail = new JobDetailFactoryBean();
//配置任务的具体实现
jobDetail.setJobClass(ScheduleJob.class);
//是否持久化
jobDetail.setDurability(true);
//出现异常是否重新执行
jobDetail.setRequestsRecovery(true);
//配置定时任务信息
// jobDetail.setName("");
// jobDetail.setGroup("");
// jobDetail.setDescription("");
return jobDetail;
}
/**
* 配置任务调度工厂,用来生成任务调度器,将一个方法产生为Bean并交给Spring容器管理
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
try {
// 设置自定义Job Factory,用于Spring管理Job bea
factory.setJobFactory(jobFactory);
//配置数据源,这是quartz使用的表的数据库
factory.setDataSource(dataSource);
//配置配置文件
factory.setQuartzProperties(properties());
//设置自动启动,默认为true
factory.setAutoStartup(true);
//开启更新job
factory.setOverwriteExistingJobs(true);
factory.setWaitForJobsToCompleteOnShutdown(true);
// 延迟启动quartz,保证job中的属性的注入
factory.setStartupDelay(30);
} catch (IOException e) {
e.printStackTrace();
}
return factory;
}
/**
* 开启当前的任务调度器
*/
@Bean(name = "scheduler")
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}
(3)任务工厂JobFactory
这里需要注意: 我注入了一个自定义的JobFactory ,解决SpringBoot不能在Quartz中注入Bean的问题
JobFactory具体实现:
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
/**
* QuartzJob工厂类 解决SpringBoot不能在Quartz中注入Bean的问题
* 这里我们需要注意 我注入了一个 自定义的JobFactory ,然后 把其设置为SchedulerFactoryBean 的 JobFactory。其目的是因为我在具体的Job 中 需要Spring 注入一些Service。
* 所以我们要自定义一个jobfactory, 让其在具体job 类实例化时 使用Spring 的API 来进行依赖注入。
*
*
* 原文链接:https://blog.csdn.net/l18848956739/article/details/86597709
*/
@Component
public class JobFactory extends AdaptableJobFactory {
/**
* AutowireCapableBeanFactory接口是BeanFactory的子类,可以连接和填充那些生命周期不被Spring管理的已存在的bean实例
*/
/**
* 注入autowire的对象工厂
*/
@Autowired
private AutowireCapableBeanFactory beanFactory;
/**
* 创建Job实例
*/
@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
// 调用父类的方法
final Object job = super.createJobInstance(bundle);
// 进行注入
beanFactory.autowireBean(job);
return job;
}
}
(4)自定义定时任务类
import com.alibaba.fastjson.JSONObject;
import com.example.quartz.entity.ScheduleJobEntity;
import com.example.quartz.entity.vo.ScheduleJobLogVO;
import com.example.quartz.service.ScheduleJobLogService;
import com.example.quartz.util.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.beans.BeanUtils;
import javax.annotation.Resource;
import java.util.Date;
/**
* @Desc 定时任务处理
*/
@Slf4j
@DisallowConcurrentExecution
public class ScheduleJob implements Job {
@Resource
private ScheduleJobLogService scheduleJobLogService;
@Override
public void execute(JobExecutionContext jobExecutionContext) {
//JobDetail jobDetail = jobExecutionContext.getJobDetail();
//Map<String, Object> jobParamsMap = jobDetail.getJobDataMap();
ScheduleJobEntity scheduleJobEntity = (ScheduleJobEntity) jobExecutionContext.getMergedJobDataMap()
.get(ScheduleJobEntity.JOB_PARAM_KEY);
String jobName = scheduleJobEntity.getJobName();
String jobGroup = scheduleJobEntity.getJobGroup();
String requestType = scheduleJobEntity.getRequestType();
String url = scheduleJobEntity.getHttpUrl();
String jsonParam = scheduleJobEntity.getHttpParams();
//任务开始时间
long startTime = System.currentTimeMillis();
log.info("task start in execute jobName:{}, 开始时间:{}", jobName, new Date());
//数据库保存执行记录
ScheduleJobLogVO scheduleJobLogVO = new ScheduleJobLogVO();
BeanUtils.copyProperties(scheduleJobEntity, scheduleJobLogVO);
try {
//执行任务
String result = chooseRequestType(requestType, url, jsonParam);
//任务执行时间,单位毫秒
long times = System.currentTimeMillis() - startTime;
scheduleJobLogVO.setTimes(String.valueOf(times));
//任务状态 0:成功 -1:失败
scheduleJobLogVO.setTaskStatus(getStatusCode(result));
log.info("Success in execute [{},{},{}]", jobName, jobGroup, "总共耗时:" + times + "毫秒");
} catch (Exception e) {
e.printStackTrace();
log.error("任务执行失败,任务:" + jobName, e);
scheduleJobLogVO.setTimes(String.valueOf(System.currentTimeMillis() - startTime));
scheduleJobLogVO.setTaskStatus("-1");
} finally {
scheduleJobLogService.insertScheduledTaskLog(scheduleJobLogVO);
}
}
/**
* resultStatus 返回0 成功,返回-1失败
*/
private String getStatusCode(String result) {
JSONObject jsonObject = JSONObject.parseObject(result);
String resultStatus = jsonObject.getString("status");
if (StringUtils.equals(resultStatus, "0")) {
return "0";
}
return "-1";
}
private String chooseRequestType(String requestType, String url, String jsonParam) {
String result = "";
if (StringUtils.equals(requestType, "POST_JSON")) {
result = HttpClientUtil.sendPostJson(url, jsonParam);
}
if (StringUtils.equals(requestType, "GET")) {
result = HttpClientUtil.sendGetRequestJson(url, jsonParam);
}
return result;
}
}
定时任务业务逻辑接口和实现类
(1)定时业务逻辑接口
import com.example.quartz.entity.ScheduleJobEntity;
import com.example.quartz.entity.vo.ScheduleJobVO;
import com.example.quartz.util.Page;
import org.quartz.SchedulerException;
import java.util.List;
/**
* 定时任务业务逻辑接口
*/
public interface ScheduleJobService {
/**
* 保存定时任务
*
* @param JobParam
*/
void addJob(ScheduleJobEntity scheduleJobEntityParam);
/**
* 更新任务cron表达式
*
* @param jobName
* @param jobGroup
* @param cronExpression
*/
void updateCronExpression(String jobName, String jobGroup, String cronExpression);
/**
* 删除任务
*
* @param jobName
* @param jobGroup
*/
void deleteJob(String jobName, String jobGroup);
/**
* 暂停任务
*
* @param jobName
* @param jobGroup
*/
void pauseJob(String jobName, String jobGroup);
/**
* 恢复任务
*
* @param jobName
* @param jobGroup
*/
void resumeJob(String jobName, String jobGroup);
/**
* 立即执行
* jobList里面参数如下
*
* @param jobName
* @param jobGroup
*/
void runJobNow(List<ScheduleJobEntity> jobList);
/**
* 获取所有计划中的任务列表
*
* @param searchParam
* @param pageSize 页面大小
* @param pageNum 页码
* @return
*/
Page<ScheduleJobVO> queryScheduleJob(String searchParam, Integer pageSize, Integer pageNum);
/**
* 所有正在运行的job
*
* @return
* @throws SchedulerException
*/
List<ScheduleJobVO> getRunningJob() throws SchedulerException;
/**
* 获取所有计划中的任务列表
*
* @return
* @throws SchedulerException
*/
List<ScheduleJobVO> getAllJob() throws SchedulerException;
}
(2)定时业务逻辑接口实现类
import com.example.quartz.constants.Constant;
import com.example.quartz.entity.ScheduleJobEntity;
import com.example.quartz.entity.vo.ScheduleJobVO;
import com.example.quartz.enu.TriggerStateEnum;
import com.example.quartz.mapper.ScheduleJobMapper;
import com.example.quartz.service.ScheduleJobService;
import com.example.quartz.util.JobUtil;
import com.example.quartz.util.JsonValidUtil;
import com.example.quartz.util.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
@Slf4j
@Service
public class ScheduleJobServiceImpl implements ScheduleJobService {
@Resource
private Scheduler scheduler;
@Autowired
private ScheduleJobMapper scheduleJobMapper;
/**
* 项目启动时,初始化定时器
*/
@PostConstruct
public void init() {
log.info("实例化List<ScheduleJob>,从数据库读取 :{}", this);
List<ScheduleJobEntity> scheduleJobEntityList = scheduleJobMapper.getAllTask();
for (ScheduleJobEntity scheduleJobEntity : scheduleJobEntityList) {
CronTrigger cronTrigger = JobUtil.getCronTrigger(scheduler, scheduleJobEntity);
// 如果不存在,则创建
if (cronTrigger == null) {
JobUtil.createScheduleJob(scheduler, scheduleJobEntity);
} else {
JobUtil.updateScheduleJob(scheduler, scheduleJobEntity);
}
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void addJob(ScheduleJobEntity JobParam) {
String jobName = JobParam.getJobName();
String jobGroup = JobParam.getJobGroup();
String jsonParamsStr = JobParam.getHttpParams();
//任务状态正常
//通过jobName和jobGroup确保任务的唯一性
ScheduleJobEntity scheduleJobEntityResult = scheduleJobMapper.getTaskByJobNameAndJobGroup(jobName, jobGroup);
if (scheduleJobEntityResult != null) {
throw new RuntimeException("任务名称重复!");
}
//对参数进行校验
if (!JsonValidUtil.isJson(jsonParamsStr)) {
throw new RuntimeException("请将请求参数转为合法的json字符串!");
}
//创建定时任务
JobUtil.createScheduleJob(scheduler, JobParam);
//新增job
scheduleJobMapper.addJob(JobParam);
}
@Override
public void pauseJob(String jobName, String jobGroup) {
String jobStatus = JobUtil.getJobStatus(scheduler, jobName, jobGroup);
if (StringUtils.equals(jobStatus, Constant.JOB_STATUS_PAUSED)) {
throw new RuntimeException("当前任务已是暂停状态!");
}
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
try {
scheduler.pauseJob(jobKey);
//暂停运行和恢复运行需要批量更新任务状态
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
@Override
public void resumeJob(String jobName, String jobGroup) {
String jobStatus = JobUtil.getJobStatus(scheduler, jobName, jobGroup);
if (!StringUtils.equals(jobStatus, Constant.JOB_STATUS_PAUSED)) {
throw new RuntimeException("任务仅在暂停状态时才能恢复!");
}
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
try {
scheduler.resumeJob(jobKey);
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
@Override
public void deleteJob(String jobName, String jobGroup) {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
TriggerKey triggerKey = JobUtil.getTriggerKey(jobName, jobGroup);
try {
scheduler.pauseTrigger(triggerKey);
scheduler.unscheduleJob(triggerKey);
scheduler.deleteJob(jobKey);
scheduleJobMapper.deletjob(jobName, jobGroup);
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
@Override
public void updateCronExpression(String jobName, String jobGroup, String cronExpression) {
TriggerKey triggerKey = JobUtil.getTriggerKey(jobName, jobGroup);
//表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
//按新的cronExpression重新构建trigger
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(triggerKey)
.withSchedule(scheduleBuilder).build();
try {
scheduler.rescheduleJob(triggerKey, trigger);
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void runJobNow(List<ScheduleJobEntity> jobList) {
for (ScheduleJobEntity scheduleJobEntity : jobList) {
JobUtil.run(scheduler, scheduleJobEntity);
}
}
@Override
public Page<ScheduleJobVO> queryScheduleJob(String searchParam, Integer pageSize, Integer pageNum) {
Integer beginIndex = (pageNum - 1) * pageSize;
Map<String, Object> sqlMap = new HashMap<>();
sqlMap.put("searchParam", searchParam);
sqlMap.put("pageSize", pageSize);
sqlMap.put("beginIndex", beginIndex);
List<ScheduleJobVO> scheduleJobVOList = scheduleJobMapper.queryScheduleJob(sqlMap);
for (ScheduleJobVO scheduleJobVO : scheduleJobVOList) {
//设置jobStatus
String jobStatus = JobUtil.getJobStatus(scheduler, scheduleJobVO.getJobName(), scheduleJobVO.getJobGroup());
scheduleJobVO.setTaskStatus(TriggerStateEnum.getTriggerState(jobStatus));
//任务状态正常,根据cron表达式计算下次运行时间
if (StringUtils.equals(jobStatus, Constant.JOB_STATUS_NORMAL)) {
scheduleJobVO.setNextFireTime(JobUtil.getNextFireDate(scheduleJobVO.getCronExpression()));
}
}
Page<ScheduleJobVO> httpJobDetailVOPageVO = new Page<>();
httpJobDetailVOPageVO.setPageNum(pageNum);
httpJobDetailVOPageVO.setPageSize(pageSize);
httpJobDetailVOPageVO.setCount(scheduleJobVOList.size());
httpJobDetailVOPageVO.setTotalCount(scheduleJobMapper.queryScheduleJobCount(sqlMap));
httpJobDetailVOPageVO.setResultList(scheduleJobVOList);
return httpJobDetailVOPageVO;
}
/**
* 所有正在运行的job
*
* @return
* @throws SchedulerException
*/
@Override
public List<ScheduleJobVO> getRunningJob() throws SchedulerException {
List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
List<ScheduleJobVO> jobList = new ArrayList<ScheduleJobVO>(executingJobs.size());
for (JobExecutionContext executingJob : executingJobs) {
ScheduleJobVO job = new ScheduleJobVO();
JobDetail jobDetail = executingJob.getJobDetail();
JobKey jobKey = jobDetail.getKey();
Trigger trigger = executingJob.getTrigger();
job.setJobName(jobKey.getName());
job.setJobGroup(jobKey.getGroup());
job.setDescription("触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
job.setTaskStatus(triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
job.setCronExpression(cronExpression);
}
jobList.add(job);
}
return jobList;
}
/**
* 获取所有计划中的任务列表
*
* @return
* @throws SchedulerException
*/
@Override
public List<ScheduleJobVO> getAllJob() throws SchedulerException {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
List<ScheduleJobVO> jobList = new ArrayList<ScheduleJobVO>();
for (JobKey jobKey : jobKeys) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
ScheduleJobEntity scheduleJobEntity = (ScheduleJobEntity) trigger.getJobDataMap().get(ScheduleJobEntity.JOB_PARAM_KEY);
ScheduleJobVO scheduleJob=new ScheduleJobVO();
BeanUtils.copyProperties(scheduleJobEntity, scheduleJob);
// scheduleJob.setJobName(jobKey.getName());
// scheduleJob.setJobGroup(jobKey.getGroup());
// scheduleJob.setDescription("触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
scheduleJob.setTaskStatus(triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
//scheduleJob.setCronExpression(cronExpression);
}
jobList.add(scheduleJob);
}
}
return jobList;
}
}
(3)定时任务执行历史记录接口
import com.example.quartz.util.Page;
import com.example.quartz.entity.vo.ScheduleJobLogVO;
import com.example.quartz.entity.vo.ScheduleJobVO;
/**
* 定时任务执行历史
*/
public interface ScheduleJobLogService {
/**
* 定时任务执行日志
*/
Page<ScheduleJobLogVO> scheduledTaskLogList(String jobName, String jobGroup, String searchParam, Integer pageSize, Integer pageNum);
/**
* 查看历史job
* @param searchParam
* @param pageSize
* @param pageNum
*/
Page<ScheduleJobVO> getHistoryTaskInfoList(String searchParam, Integer pageSize, Integer pageNum);
int insertScheduledTaskLog(ScheduleJobLogVO scheduleJobLogVO);
}
(4)定时任务执行历史记录接口实现类
import com.example.quartz.util.Page;
import com.example.quartz.entity.vo.ScheduleJobLogVO;
import com.example.quartz.entity.vo.ScheduleJobVO;
import com.example.quartz.mapper.ScheduleJobLogMapper;
import com.example.quartz.mapper.ScheduleJobMapper;
import com.example.quartz.service.ScheduleJobLogService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class ScheduleJobLogServiceImpl implements ScheduleJobLogService {
private static final Logger logger = LogManager.getLogger(ScheduleJobLogServiceImpl.class);
@Autowired
private ScheduleJobLogMapper scheduleJobLogMapper;
@Autowired
private ScheduleJobMapper scheduleJobMapper;
@Override
public Page<ScheduleJobLogVO> scheduledTaskLogList(String jobName, String jobGroup, String searchParam, Integer pageSize, Integer pageNum) {
Integer beginIndex = (pageNum - 1) * pageSize;
Map<String, Object> sqlMap = new HashMap<>();
sqlMap.put("jobName", jobName);
sqlMap.put("jobGroup", jobGroup);
sqlMap.put("searchParam", searchParam);
sqlMap.put("pageSize", pageSize);
sqlMap.put("beginIndex", beginIndex);
List<ScheduleJobLogVO> scheduleJobLogVOList = scheduleJobLogMapper.queryscheduledTaskLog(sqlMap);
Page<ScheduleJobLogVO> httpJobDetailVOPageVO = new Page<>();
httpJobDetailVOPageVO.setPageNum(pageNum);
httpJobDetailVOPageVO.setPageSize(pageSize);
httpJobDetailVOPageVO.setCount(scheduleJobLogVOList.size());
httpJobDetailVOPageVO.setTotalCount(scheduleJobLogMapper.queryscheduledTaskLogCount(sqlMap));
httpJobDetailVOPageVO.setResultList(scheduleJobLogVOList);
return httpJobDetailVOPageVO;
}
@Override
public Page<ScheduleJobVO> getHistoryTaskInfoList(String searchParam, Integer pageSize, Integer pageNum) {
Integer beginIndex = (pageNum - 1) * pageSize;
Map<String, Object> sqlMap = new HashMap<>();
sqlMap.put("searchParam", searchParam);
sqlMap.put("pageSize", pageSize);
sqlMap.put("beginIndex", beginIndex);
List<ScheduleJobVO> scheduleJobVOList = scheduleJobMapper.queryHistoryTaskInfoList(sqlMap);
Page<ScheduleJobVO> httpJobDetailVOPageVO = new Page<>();
httpJobDetailVOPageVO.setPageNum(pageNum);
httpJobDetailVOPageVO.setPageSize(pageSize);
httpJobDetailVOPageVO.setCount(scheduleJobVOList.size());
httpJobDetailVOPageVO.setTotalCount(scheduleJobMapper.queryHistoryTaskInfoListCount(sqlMap));
httpJobDetailVOPageVO.setResultList(scheduleJobVOList);
return httpJobDetailVOPageVO;
}
@Override
public int insertScheduledTaskLog(ScheduleJobLogVO scheduleJobLogVO) {
return scheduleJobLogMapper.insertScheduledTaskLog(scheduleJobLogVO);
}
}
定时业务 mapper接口和mapper.XML
(1)定时任务业务逻辑mapper接口
import com.example.quartz.entity.ScheduleJobEntity;
import com.example.quartz.entity.vo.ScheduleJobVO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Repository
public interface ScheduleJobMapper {
/**
* 获取所有任务(用于初始化)
*/
public List<ScheduleJobEntity> getAllTask();
/**
* 查询调度job
*/
List<ScheduleJobVO> queryScheduleJob(Map<String, Object> map);
/**
* 通过 job名字和job分组获取任务
*/
ScheduleJobEntity getTaskByJobNameAndJobGroup(@Param("jobName") String jobName, @Param("jobGroup") String jobGroup);
Integer queryScheduleJobCount(Map<String, Object> map);
/**
* 新增定时任务
*/
int addJob(ScheduleJobEntity scheduleJobEntity);
List<ScheduleJobVO> queryHistoryTaskInfoList(Map<String, Object> map);
Integer queryHistoryTaskInfoListCount(Map<String, Object> map);
Integer deletjob(@Param("jobName") String jobName, @Param("jobGroup") String jobGroup);
}
(2)定时任务执行记录mapper接口
@Repository
public interface ScheduleJobLogMapper {
int insertScheduledTaskLog(ScheduleJobLogVO scheduleJobLogVO);
List<ScheduleJobLogVO> queryscheduledTaskLog(Map<String, Object> map);
Integer queryscheduledTaskLogCount(Map<String, Object> map);
}
(3)定时任务业务逻辑mapper.xml
<?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.example.quartz.mapper.ScheduleJobMapper">
<resultMap id="BaseResultMap" type="com.example.quartz.entity.ScheduleJobEntity">
<id column="ID" jdbcType="BIGINT" property="jobId"/>
<result column="JOB_NAME" jdbcType="VARCHAR" property="jobName"/>
<result column="JOB_GROUP" jdbcType="VARCHAR" property="jobGroup"/>
<result column="DESCRIPTION" jdbcType="VARCHAR" property="description"/>
<result column="REQUEST_TYPE" jdbcType="VARCHAR" property="requestType"/>
<result column="HTTP_URL" jdbcType="VARCHAR" property="httpUrl"/>
<result column="HTTP_PARAMS" jdbcType="VARCHAR" property="httpParams"/>
<result column="CRON_EXPRESSION" jdbcType="VARCHAR" property="cronExpression"/>
<result column="CREATE_TIME" jdbcType="TIMESTAMP" property="createTime"/>
<result column="UPDATE_TIME" jdbcType="TIMESTAMP" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
ID
,JOB_NAME,JOB_GROUP,DESCRIPTION,REQUEST_TYPE,HTTP_URL,HTTP_PARAMS,TASK_STATUS, CRON_EXPRESSION, CREATE_TIME,UPDATE_TIME
</sql>
<select id="getTaskByJobNameAndJobGroup" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from schedule_job
where JOB_NAME = #{jobName} and JOB_GROUP = #{jobGroup}
</select>
<select id="getAllTask" resultMap="BaseResultMap">
SELECT t.JOB_NAME,
t.JOB_GROUP,
ct.CRON_EXPRESSION,
hd.ID,
hd.DESCRIPTION,
hd.REQUEST_TYPE,
hd.HTTP_URL,
hd.HTTP_PARAMS,
hd.TASK_STATUS,
hd.CRON_EXPRESSION,
hd.CREATE_TIME,
hd.UPDATE_TIME
FROM QRTZ_TRIGGERS t
LEFT JOIN QRTZ_CRON_TRIGGERS ct
ON (t.TRIGGER_NAME = ct.TRIGGER_NAME AND t.TRIGGER_GROUP = ct.TRIGGER_GROUP)
LEFT JOIN schedule_job hd ON (t.JOB_NAME = hd.JOB_NAME AND t.JOB_GROUP = hd.JOB_GROUP)
WHERE 1 = 1
</select>
<insert id="addJob" parameterType="com.example.quartz.entity.ScheduleJobEntity">
insert into schedule_job
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="jobId != null">
ID,
</if>
<if test="jobName != null">
JOB_NAME,
</if>
<if test="jobGroup != null">
JOB_GROUP,
</if>
<if test="description != null">
DESCRIPTION,
</if>
<if test="requestType != null">
REQUEST_TYPE,
</if>
<if test="httpUrl != null">
HTTP_URL,
</if>
<if test="httpParams != null">
HTTP_PARAMS,
</if>
<if test="cronExpression != null">
CRON_EXPRESSION,
</if>
<if test="taskStatus != null">
TASK_STATUS,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="jobId != null">
#{jobId,jdbcType=BIGINT},
</if>
<if test="jobName != null">
#{jobName,jdbcType=VARCHAR},
</if>
<if test="jobGroup != null">
#{jobGroup,jdbcType=VARCHAR},
</if>
<if test="description != null">
#{description,jdbcType=VARCHAR},
</if>
<if test="requestType != null">
#{requestType,jdbcType=VARCHAR},
</if>
<if test="httpUrl != null">
#{httpUrl,jdbcType=VARCHAR},
</if>
<if test="httpParams != null">
#{httpParams,jdbcType=VARCHAR},
</if>
<if test="cronExpression != null">
#{cronExpression,jdbcType=VARCHAR},
</if>
<if test="taskStatus != null">
#{taskStatus,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<resultMap id="JobDetailMap" type="com.example.quartz.entity.vo.ScheduleJobVO">
<id column="ID" jdbcType="BIGINT" property="jobId"/>
<result column="JOB_NAME" jdbcType="VARCHAR" property="jobName"/>
<result column="JOB_GROUP" jdbcType="VARCHAR" property="jobGroup"/>
<result column="DESCRIPTION" jdbcType="VARCHAR" property="description"/>
<result column="REQUEST_TYPE" jdbcType="VARCHAR" property="requestType"/>
<result column="HTTP_URL" jdbcType="VARCHAR" property="httpUrl"/>
<result column="HTTP_PARAMS" jdbcType="VARCHAR" property="httpParams"/>
<result column="CRON_EXPRESSION" jdbcType="VARCHAR" property="cronExpression"/>
<result column="TASK_STATUS" jdbcType="VARCHAR" property="taskStatus"/>
<result column="CREATE_TIME" jdbcType="TIMESTAMP" property="createTime"/>
<result column="UPDATE_TIME" jdbcType="TIMESTAMP" property="updateTime"/>
</resultMap>
<select id="queryScheduleJob" resultMap="JobDetailMap">
SELECT
t.JOB_NAME,
t.JOB_GROUP,
hd.ID,
hd.DESCRIPTION,
hd.REQUEST_TYPE,
hd.HTTP_URL,
hd.HTTP_PARAMS,
hd.TASK_STATUS,
hd.CREATE_TIME,
hd.UPDATE_TIME,
ct.CRON_EXPRESSION
FROM
QRTZ_TRIGGERS t
LEFT JOIN QRTZ_CRON_TRIGGERS ct ON ( t.TRIGGER_NAME = ct.TRIGGER_NAME AND t.TRIGGER_GROUP = ct.TRIGGER_GROUP )
LEFT JOIN schedule_job hd ON ( t.JOB_NAME = hd.JOB_NAME AND t.JOB_GROUP = hd.JOB_GROUP )
WHERE
1=1
<if test="searchParam != null and searchParam != ''">
AND ( t.JOB_NAME LIKE concat('%',#{searchParam},'%') OR t.JOB_GROUP LIKE concat('%',#{searchParam},'%') )
</if>
ORDER BY hd.ID DESC
<if test="beginIndex != null and pageSize!=null">
limit #{beginIndex},#{pageSize}
</if>
</select>
<select id="queryScheduleJobCount" resultType="java.lang.Integer">
SELECT
COUNT(1)
FROM
QRTZ_TRIGGERS t
LEFT JOIN QRTZ_CRON_TRIGGERS ct ON ( t.TRIGGER_NAME = ct.TRIGGER_NAME AND t.TRIGGER_GROUP = ct.TRIGGER_GROUP )
LEFT JOIN schedule_job hd ON ( t.JOB_NAME = hd.JOB_NAME AND t.JOB_GROUP = hd.JOB_GROUP )
WHERE
1=1
<if test="searchParam != null and searchParam != ''">
AND ( t.JOB_NAME LIKE concat('%',#{searchParam},'%') OR t.JOB_GROUP LIKE concat('%',#{searchParam},'%') )
</if>
</select>
<select id="queryHistoryTaskInfoList" resultMap="JobDetailMap">
SELECT
hd.ID,
hd.JOB_NAME,
hd.JOB_GROUP,
hd.DESCRIPTION,
hd.REQUEST_TYPE,
hd.HTTP_URL,
hd.HTTP_PARAMS,
hd.TASK_STATUS,
hd.CREATE_TIME,
hd.UPDATE_TIME
FROM schedule_job hd
LEFT JOIN QRTZ_TRIGGERS qt ON ( hd.JOB_NAME = qt.JOB_NAME AND hd.JOB_GROUP = qt.JOB_GROUP )
WHERE
(qt.JOB_NAME IS NULL AND qt.JOB_GROUP IS NULL)
<if test="searchParam != null and searchParam != ''">
AND ( hd.JOB_NAME LIKE concat('%',#{searchParam},'%') OR hd.JOB_GROUP LIKE concat('%',#{searchParam},'%') )
</if>
ORDER BY hd.ID DESC
<if test="beginIndex != null and pageSize!=null">
limit #{beginIndex},#{pageSize}
</if>
</select>
<select id="queryHistoryTaskInfoListCount" resultType="java.lang.Integer">
SELECT
COUNT(1)
FROM
schedule_job hd
LEFT JOIN QRTZ_TRIGGERS qt ON ( hd.JOB_NAME = qt.JOB_NAME AND hd.JOB_GROUP = qt.JOB_GROUP )
WHERE
(qt.JOB_NAME IS NULL AND qt.JOB_GROUP IS NULL)
<if test="searchParam != null and searchParam != ''">
AND ( hd.JOB_NAME LIKE concat('%',#{searchParam},'%') OR hd.JOB_GROUP LIKE concat('%',#{searchParam},'%') )
</if>
</select>
<select id="deletjob" resultType="java.lang.Integer">
delete
from schedule_job
where JOB_NAME = #{jobName}
and JOB_GROUP = #{jobGroup}
</select>
</mapper>
(4)定时任务执行记录mapper.xml
<?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.example.quartz.mapper.ScheduleJobLogMapper">
<resultMap id="BaseResultMap" type="com.example.quartz.entity.vo.ScheduleJobLogVO">
<id column="ID" jdbcType="BIGINT" property="id"/>
<result column="JOB_ID" jdbcType="BIGINT" property="jobId"/>
<result column="JOB_NAME" jdbcType="VARCHAR" property="jobName"/>
<result column="JOB_GROUP" jdbcType="VARCHAR" property="jobGroup"/>
<result column="DESCRIPTION" jdbcType="VARCHAR" property="description"/>
<result column="REQUEST_TYPE" jdbcType="VARCHAR" property="requestType"/>
<result column="HTTP_URL" jdbcType="VARCHAR" property="httpUrl"/>
<result column="HTTP_PARAMS" jdbcType="VARCHAR" property="httpParams"/>
<result column="cron_expression" jdbcType="VARCHAR" property="cronExpression"/>
<result column="TASK_STATUS" jdbcType="VARCHAR" property="taskStatus"/>
<result column="times" jdbcType="VARCHAR" property="times"/>
<result column="CREATE_TIME" jdbcType="TIMESTAMP" property="createTime"/>
<result column="UPDATE_TIME" jdbcType="TIMESTAMP" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
ID,JOB_ID,JOB_NAME,JOB_GROUP,DESCRIPTION,REQUEST_TYPE,HTTP_URL,HTTP_PARAMS,cron_expression,TASK_STATUS,times,CREATE_TIME,UPDATE_TIME
</sql>
<insert id="insertScheduledTaskLog" parameterType="com.example.quartz.entity.vo.ScheduleJobLogVO">
insert into schedule_job_log
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
ID,
</if>
<if test="jobId != null">
JOB_ID,
</if>
<if test="jobName != null">
JOB_NAME,
</if>
<if test="jobGroup != null">
JOB_GROUP,
</if>
<if test="description != null">
DESCRIPTION,
</if>
<if test="requestType != null">
REQUEST_TYPE,
</if>
<if test="httpUrl != null">
HTTP_URL,
</if>
<if test="httpParams != null">
HTTP_PARAMS,
</if>
<if test="cronExpression != null">
cron_expression,
</if>
<if test="taskStatus != null">
TASK_STATUS,
</if>
<if test="times != null">
times,
</if>
<if test="createTime != null">
CREATE_TIME,
</if>
<if test="updateTime != null">
UPDATE_TIME,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=BIGINT},
</if>
<if test="jobId != null">
#{jobId,jdbcType=BIGINT},
</if>
<if test="jobName != null">
#{jobName,jdbcType=VARCHAR},
</if>
<if test="jobGroup != null">
#{jobGroup,jdbcType=VARCHAR},
</if>
<if test="description != null">
#{description,jdbcType=VARCHAR},
</if>
<if test="requestType != null">
#{requestType,jdbcType=VARCHAR},
</if>
<if test="httpUrl != null">
#{httpUrl,jdbcType=VARCHAR},
</if>
<if test="httpParams != null">
#{httpParams,jdbcType=VARCHAR},
</if>
<if test="cronExpression != null">
#{cronExpression,jdbcType=VARCHAR},
</if>
<if test="taskStatus != null ">
#{taskStatus,jdbcType=VARCHAR},
</if>
<if test="times != null">
#{times,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
#{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
<select id="queryscheduledTaskLog" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM
schedule_job_log t
WHERE
1=1
<if test="jobName != null and jobName != ''">
AND t.JOB_NAME = #{jobName}
</if>
<if test="jobGroup != null and jobGroup != ''">
AND t.JOB_GROUP = #{jobGroup}
</if>
<if test="searchParam != null and searchParam != ''">
AND ( t.JOB_NAME LIKE concat('%',#{searchParam},'%') OR t.JOB_GROUP LIKE concat('%',#{searchParam},'%') )
</if>
ORDER BY t.ID DESC
<if test="beginIndex != null and pageSize!=null">
limit #{beginIndex},#{pageSize}
</if>
</select>
<select id="queryscheduledTaskLogCount" resultType="java.lang.Integer">
SELECT
COUNT(1)
FROM
schedule_job_log t
WHERE
1=1
<if test="jobName != null and jobName != ''">
AND t.JOB_NAME = #{jobName}
</if>
<if test="jobGroup != null and jobGroup != ''">
AND t.JOB_GROUP = #{jobGroup}
</if>
<if test="searchParam != null and searchParam != ''">
AND ( t.JOB_NAME LIKE concat('%',#{searchParam},'%') OR t.JOB_GROUP LIKE concat('%',#{searchParam},'%') )
</if>
</select>
</mapper>
定时任务用到的bean
(1)定时任务entity
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 定时任务bean
*/
@Data
public class ScheduleJobEntity implements Serializable {
private static final long serialVersionUID = -50190044894125802L;
/**
* 任务调度参数key
*/
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
/**
* jobId
*/
private Long jobId;
/**
* 任务名称不能为空
*/
private String jobName;
/**
* 任务分组不能为空
*/
private String jobGroup;
/**
* 任务描述
*/
private String description;
/**
* 请求类型{GET POST}
*/
private String requestType;
/**
* 请求URL不能为空
*/
private String httpUrl;
/**
* 请求参数{参数可以为空,必须是json格式}
*/
private String httpParams;
/**
* cron表达式
*/
private String cronExpression;
/**
* 创建时间
*/
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 更新时间
*/
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
(2)定时任务VO
@Data
@Api(value = "定时任务返参")
public class ScheduleJobVO {
/**
* jobId
*/
private Long jobId;
/**
* 任务名称
*/
private String jobName;
/**
* 任务分组
*/
private String jobGroup;
/**
* 任务描述
*/
private String description;
/**
* 请求类型{GET POST}
*/
private String requestType;
/**
* 请求URL
*/
private String httpUrl;
/**
* 请求参数{参数可以为空,必须是json格式}
*/
private String httpParams;
/**
* cron表达式
*/
private String cronExpression;
/**
* NONE:不存在, NORMAL:正常, PAUSE:暂停, COMPLETE:完成, ERROR:错误, BLOCKED:阻塞
*/
private String taskStatus;
/**
* 下次执行时间
*/
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date nextFireTime;
/**
* 创建时间
*/
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 更新时间
*/
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
(3)定时任务日志VO
@Data
@Api(value = "定时任务日志返参")
public class ScheduleJobLogVO implements Serializable {
private static final long serialVersionUID = 2259203435361774854L;
/**
* 日志id
*/
private Long id;
/**
* jobId
*/
private Long jobId;
/**
* 任务名称不能为空
*/
private String jobName;
/**
* 任务分组不能为空
*/
private String jobGroup;
/**
* 任务描述
*/
private String description;
/**
* 请求类型{GET POST}
*/
private String requestType;
/**
* 请求URL不能为空
*/
private String httpUrl;
/**
* 请求参数{参数可以为空,必须是json格式}
*/
private String httpParams;
/**
* cron表达式
*/
private String cronExpression;
/**
* 执行状态 0:成功 -1失败
*/
private String taskStatus;
/**
* 执行时间:单位毫秒
*/
private String times;
/**
* 创建时间
*/
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 更新时间
*/
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
(4)添加定时任务入参
import io.swagger.annotations.Api;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
@Data
@Api("添加任务请求参数")
public class AddScheduleJobParam {
@NotEmpty(message = "任务名称不能为空")
private String jobName;
@NotEmpty(message = "任务分组不能为空")
private String jobGroup;
/**
* 描述
*/
private String description;
/**
* 请求类型
*/
@NotEmpty(message = "请求类型不能为空")
private String requestType;
/**
* 请求URL不能为空
*/
@NotEmpty(message = "请求URL不能为空")
private String httpUrl;
/**
* 请求参数{参数可以为空,必须是json格式}
*/
private String httpParams;
/**
* cron表达式
*/
@NotEmpty(message = "cron表达式不能为空")
private String cronExpression;
}
定时任务用到的工具类
(1)定时任务工具类
import com.example.quartz.constants.Constant;
import com.example.quartz.entity.ScheduleJobEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import java.text.ParseException;
import java.util.Date;
/**
* 定时任务工具类
*/
@Slf4j
public class JobUtil {
private final static String JOB_NAME = "TASK_";
/**
* 获取触发器key
*/
public static TriggerKey getTriggerKey(Long jobId) {
return TriggerKey.triggerKey(JOB_NAME + jobId);
}
/**
* 根据jobName和jobGroup生成triggerKey
*/
public static TriggerKey getTriggerKey(String jobName, String jobGroup) {
String triggerName = Constant.TRIGGER_PREFIX + jobName;
String triggerGroup = Constant.TRIGGER_PREFIX + jobGroup;
return TriggerKey.triggerKey(triggerName, triggerGroup);
}
/**
* 获取jobKey
*/
public static JobKey getJobKey(Long jobId) {
return JobKey.jobKey(JOB_NAME + jobId);
}
/**
* 获取jobKey
*/
public static JobKey getJobKey(String jobName, String jobGroup) {
return JobKey.jobKey(jobName, jobGroup);
}
/**
* 获取表达式触发器
*/
public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
try {
return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
} catch (SchedulerException e) {
throw new RuntimeException("获取定时任务CronTrigger出现异常", e);
}
}
/**
* 获取表达式触发器
*/
public static CronTrigger getCronTrigger(Scheduler scheduler, ScheduleJobEntity scheduleJobEntity) {
TriggerKey triggerKey = getTriggerKey(scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
try {
return (CronTrigger) scheduler.getTrigger(triggerKey);
} catch (SchedulerException e) {
throw new RuntimeException("获取定时任务CronTrigger出现异常", e);
}
}
/**
* 获取job状态
*
* @param jobName
* @param jobGroup
* @return
*/
public static String getJobStatus(Scheduler scheduler, String jobName, String jobGroup) {
String jobStatus = "";
TriggerKey triggerKey = getTriggerKey(jobName, jobGroup);
try {
jobStatus = scheduler.getTriggerState(triggerKey).name();
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
return jobStatus;
}
/**
* 创建定时任务
*/
public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJobEntity) {
try {
JobKey JobKey = getJobKey(scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
// 通过JobBuilder构建JobDetail实例
JobDetail jobDetail = JobBuilder.newJob(com.example.quartz.job.ScheduleJob.class).withIdentity(JobKey).build();
// 表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJobEntity.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
TriggerKey triggerKey = getTriggerKey(scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJobEntity);
// 开启调度
scheduler.scheduleJob(jobDetail, trigger);
//获取job状态
String jobStatus = JobUtil.getJobStatus(scheduler, scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
//暂停任务
if (StringUtils.equals(jobStatus, Constant.JOB_STATUS_PAUSED)) {
pauseJob(scheduler, scheduleJobEntity);
}
log.info("Success in addJob, [{}]-[{}]", scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
} catch (SchedulerException e) {
throw new RuntimeException("创建定时任务失败", e);
}
}
/**
* 更新定时任务
*/
public static void updateScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJobEntity) {
try {
TriggerKey triggerKey = getTriggerKey(scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJobEntity.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = getCronTrigger(scheduler, scheduleJobEntity);
//按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//放入参数
trigger.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJobEntity);
scheduler.rescheduleJob(triggerKey, trigger);
String jobStatus = JobUtil.getJobStatus(scheduler, scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
//暂停任务
if (StringUtils.equals(jobStatus, Constant.JOB_STATUS_PAUSED)) {
pauseJob(scheduler, scheduleJobEntity);
}
} catch (SchedulerException e) {
throw new RuntimeException("更新定时任务失败", e);
}
}
/**
* 立即执行任务
*/
public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJobEntity) {
try {
//参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJobEntity);
JobKey JobKey = getJobKey(scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
scheduler.triggerJob(JobKey, dataMap);
} catch (SchedulerException e) {
throw new RuntimeException("立即执行定时任务失败", e);
}
}
/**
* 暂停任务
*/
public static void pauseJob(Scheduler scheduler, Long jobId) {
try {
scheduler.pauseJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RuntimeException("暂停定时任务失败", e);
}
}
/**
* 暂停任务
*/
public static void pauseJob(Scheduler scheduler, ScheduleJobEntity scheduleJobEntity) {
try {
JobKey JobKey = getJobKey(scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
scheduler.pauseJob(JobKey);
} catch (SchedulerException e) {
throw new RuntimeException("暂停定时任务失败", e);
}
}
/**
* 恢复任务
*/
public static void resumeJob(Scheduler scheduler, ScheduleJobEntity scheduleJobEntity) {
try {
String jobStatus = getJobStatus(scheduler, scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
JobKey JobKey = getJobKey(scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
if (StringUtils.equals(jobStatus, Constant.JOB_STATUS_PAUSED)) {
scheduler.resumeJob(JobKey);
}
} catch (SchedulerException e) {
throw new RuntimeException("暂停定时任务失败", e);
}
}
/**
* 批量删除定时任务
*/
public static void deleteScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJobEntity) {
try {
JobKey JobKey = getJobKey(scheduleJobEntity.getJobName(), scheduleJobEntity.getJobGroup());
scheduler.deleteJob(JobKey);
} catch (SchedulerException e) {
throw new RuntimeException("删除定时任务失败", e);
}
}
/**
* 根据cron表达式获取下次执行时间
*
* @param cronExpression
* @return
*/
public static Date getNextFireDate(String cronExpression) {
try {
CronExpression cron = new CronExpression(cronExpression);
Date nextFireDate = cron.getNextValidTimeAfter(new Date());
return nextFireDate;
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
(2)Httpclient工具类
import org.apache.commons.codec.Charsets;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* Httpclient请求工具类
*/
public class HttpClientUtil {
/**
* 连接主机超时(30s)
*/
public static final int HTTP_CONNECT_TIMEOUT_30S = 30 * 1000;
/**
* 从主机读取数据超时(3min)
*/
public static final int HTTP_READ_TIMEOUT_3MIN = 180 * 1000;
/**
* HTTP成功状态码(200)
*/
public static final int HTTP_SUCCESS_STATUS_CODE = 200;
private static final Logger logger = LogManager.getLogger(HttpClientUtil.class);
private HttpClientUtil() {
}
/**
* get请求 参数为map,格式为json
*/
public static String sendGetRequestMap(String url, Map<String, Object> formDataParam) {
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String result = "";
// 超时时间设置
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(HTTP_READ_TIMEOUT_3MIN)
.setConnectTimeout(HTTP_CONNECT_TIMEOUT_30S).build();
try {
URIBuilder builder = new URIBuilder(url);
if (null != formDataParam && formDataParam.size() > 0) {
// 创建参数队列
List<NameValuePair> formParams = new ArrayList<>();
for (Entry<String, Object> entry : formDataParam.entrySet()) {
formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
}
builder.setParameters(formParams);
}
// 设置参数
HttpGet httpGet = new HttpGet(builder.build());
httpGet.setConfig(requestConfig);
// 发送请求
response = httpclient.execute(httpGet);
result = EntityUtils.toString(response.getEntity(), Charsets.UTF_8);
if (response.getStatusLine().getStatusCode() != HTTP_SUCCESS_STATUS_CODE) {
logger.error("Error in getMap. Request URL is [{}], params [{}]. Result:[{}]", url, formDataParam, result);
}
} catch (Exception e) {
logger.error("Error in getMap", e);
} finally {
HttpClientUtils.closeQuietly(httpclient);
HttpClientUtils.closeQuietly(response);
}
return result;
}
/**
* * 发送Get请求,参数json字符串
*/
public static String sendGetRequestJson(String url, String json) {
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String result = "";
// 超时时间设置
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(HTTP_READ_TIMEOUT_3MIN)
.setConnectTimeout(HTTP_CONNECT_TIMEOUT_30S).build();
try {
URIBuilder builder = new URIBuilder(url);
if (StringUtils.isNotBlank(json)) {
// 创建参数队列
List<NameValuePair> paramsList = new ArrayList<>();
paramsList.add(new BasicNameValuePair(json, json));
builder.setParameters(paramsList);
}
// 设置参数
HttpGet httpGet = new HttpGet(builder.build());
httpGet.setConfig(requestConfig);
// 发送请求
response = httpclient.execute(httpGet);
result = EntityUtils.toString(response.getEntity(), Charsets.UTF_8);
if (response.getStatusLine().getStatusCode() != HTTP_SUCCESS_STATUS_CODE) {
logger.error("Error in getMap. Request URL is [{}], params [{}]. Result:[{}]", url, json, result);
}
} catch (Exception e) {
logger.error("Error in getMap", e);
} finally {
HttpClientUtils.closeQuietly(httpclient);
HttpClientUtils.closeQuietly(response);
}
return result;
}
/**
* 发送post请求,参数json字符串
*
* @param url
* @param jsonParam json字符串
* @return 返回为字符串
*/
public static String sendPostJson(String url, String jsonParam) {
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String result = "";
// 超时时间设置
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(HTTP_READ_TIMEOUT_3MIN)
.setConnectTimeout(HTTP_CONNECT_TIMEOUT_30S).build();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
if (StringUtils.isBlank(jsonParam)) {
jsonParam = "";
}
// 设置请求头和请求参数
StringEntity entity = new StringEntity(jsonParam, "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
try {
// 发送请求
response = httpclient.execute(httpPost);
result = EntityUtils.toString(response.getEntity(), Charsets.UTF_8);
int statusCode = response.getStatusLine().getStatusCode();
if (response.getStatusLine().getStatusCode() != HTTP_SUCCESS_STATUS_CODE) {
logger.error("Error in postJson. Request URL is [{}], params [{}]. Result:[{}]", url, jsonParam, result);
}
logger.info("success in execute : result:{}", result);
System.out.println(" success in execute result: " + result);
} catch (Exception e) {
logger.error("Error in postJson", e);
} finally {
HttpClientUtils.closeQuietly(httpclient);
HttpClientUtils.closeQuietly(response);
}
return result;
}
/**
* postFormData
*/
public static String sendPostRequestMap(String url, Map<String, Object> formDataParam) {
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String result = "";
// 超时时间设置
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(HTTP_READ_TIMEOUT_3MIN)
.setConnectTimeout(HTTP_CONNECT_TIMEOUT_30S).build();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
try {
if (null != formDataParam && formDataParam.size() > 0) {
// 创建参数队列
List<NameValuePair> formParams = new ArrayList<>();
for (Entry<String, Object> entry : formDataParam.entrySet()) {
formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
}
// 设置参数
UrlEncodedFormEntity urlEntity = new UrlEncodedFormEntity(formParams, Charsets.UTF_8);
httpPost.setEntity(urlEntity);
}
// 发送请求
response = httpclient.execute(httpPost);
result = EntityUtils.toString(response.getEntity(), Charsets.UTF_8);
if (response.getStatusLine().getStatusCode() != HTTP_SUCCESS_STATUS_CODE) {
logger.error("Error in postFormData. Request URL is [{}], params [{}]. Result:[{}]", url, formDataParam, result);
}
} catch (Exception e) {
logger.error("Error in postFormData", e);
} finally {
HttpClientUtils.closeQuietly(httpclient);
HttpClientUtils.closeQuietly(response);
}
return result;
}
}
(3)分页工具类
public class Page<T> {
/**
* 当前页
*/
private Integer pageNum;
/**
* 每页数量
*/
private Integer pageSize;
/**
* 条数
*/
private Integer count;
/**
* 页数
*/
private Integer pageCount;
/**
* 总条数
*/
private Integer totalCount;
/**
* 分页结果集
*/
private List<T> resultList;
public Page() {
}
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public Integer getPageCount() {
return pageCount;
}
public void setPageCount(Integer pageCount) {
this.pageCount = pageCount;
}
public Integer getTotalCount() {
return totalCount;
}
public void setTotalCount(Integer totalCount) {
this.totalCount = totalCount;
if (totalCount % pageSize == 0) {
this.pageCount = totalCount / pageSize;
} else {
this.pageCount = totalCount / pageSize + 1;
}
}
public List<T> getResultList() {
return resultList;
}
public void setResultList(List<T> resultList) {
this.resultList = resultList;
}
}
(4)返回结果封装工具类
import com.example.quartz.enu.ResultEnum;
import java.io.Serializable;
/**
* 返回结果封装类
*/
public class Response<T> implements Serializable {
private static final long serialVersionUID = 676473785338095291L;
private int status;
private String message;
private T data;
public Response() {
}
public Response(int status, String message) {
this.status = status;
this.message = message;
}
public Response(ResultEnum resultEnum) {
this.status = resultEnum.getStatus();
this.message = resultEnum.getMessage();
}
public Response(ResultEnum resultEnum, T data) {
this.status = resultEnum.getStatus();
this.message = resultEnum.getMessage();
this.data = data;
}
public static Response error() {
return new Response(ResultEnum.ERROR);
}
public static Response error(String errorMessage) {
return new Response(ResultEnum.ERROR.getStatus(), errorMessage);
}
public static Response success() {
return new Response(ResultEnum.SUCCESS);
}
public static <T> Response success(T data) {
return new Response(ResultEnum.SUCCESS, data);
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
(5)JSON参数格式校验工具类
import com.alibaba.fastjson.JSONObject;
/**
* JSON校验工具类
*/
public class JsonValidUtil {
/**
* 判断字符串是否为json格式
*
* @param jsonStr
* @return
*/
public static boolean isJson(String jsonStr) {
try {
JSONObject.parseObject(jsonStr);
return true;
} catch (Exception e) {
return false;
}
}
}
定时任务常量类和枚举
(1)定时任务常量类
/**
* 常量类
*/
public class Constant {
/**
* trigger名称前缀
*/
public static final String TRIGGER_PREFIX = "Trigger_";
public static final String URL = "url";
public static final String PARAMS = "params";
public static final String REQUEST_TYPE = "requestType";
/**
* RequestType请求类型
*/
public static final String POST_JSON = "POST_JSON";
public static final String POST_FORM_DATA = "POST_FORM";
public static final String GET = "GET";
/**
* job状态 NORMAL
*/
public static final String JOB_STATUS_NORMAL = "NORMAL";
/**
* job状态 PAUSED :暂停
*/
public static final String JOB_STATUS_PAUSED = "PAUSED";
}
(2)定时任务状态枚举
/**
* 触发器状态枚举
*/
public enum TriggerStateEnum {
/**
* 不存在
*/
NONE("不存在"),
/**
* 正常
*/
NORMAL("正常"),
/**
* 暂停
*/
PAUSED("暂停"),
/**
* 完成
*/
COMPLETE("完成"),
/**
* 错误
*/
ERROR("失败"),
/**
* 阻塞
*/
BLOCKED("阻塞");
private String desc;
public String getDesc() {
return desc;
}
TriggerStateEnum(String desc) {
this.desc = desc;
}
public static String getTriggerState(String desc) {
for (TriggerStateEnum triggerStateEnum : values()) {
if (triggerStateEnum.name().equals(desc)) {
return triggerStateEnum.desc;
}
}
return null;
}
public static String getState(String str) {
TriggerStateEnum stateEnum = TriggerStateEnum.valueOf("NONE");
return stateEnum != null ? stateEnum.desc : null;
}
public static void main(String[] args) {
System.out.println(getState("NONE"));
System.out.println(getTriggerState("ERROR"));
}
}
(3)返回状态码及异常信息枚举类
/**
* 返回状态码及异常信息枚举类
*/
public enum ResultEnum {
SUCCESS(0, "Success"),
ERROR(-1, "Error");
private int status;
private String message;
ResultEnum(int status, String message) {
this.status = status;
this.message = message;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
定时任务功能Controller
import com.example.quartz.util.Response;
import com.example.quartz.util.Page;
import com.example.quartz.entity.ScheduleJobEntity;
import com.example.quartz.entity.param.AddScheduleJobParam;
import com.example.quartz.entity.vo.ScheduleJobVO;
import com.example.quartz.service.ScheduleJobService;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* 定时任务功能Controller
*/
@RestController
@RequestMapping(value = "/quartz/job")
@Slf4j
public class ScheduleJobController {
@Autowired
private ScheduleJobService scheduleJobService;
@ApiOperation(value = "添加job", notes = "添加job")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Response addPostJsonJob(@RequestBody @Valid AddScheduleJobParam addJobParam) {
ScheduleJobEntity scheduleJobEntityParam = new ScheduleJobEntity();
BeanUtils.copyProperties(addJobParam, scheduleJobEntityParam);
scheduleJobService.addJob(scheduleJobEntityParam);
return Response.success();
}
@ApiOperation(value = "修改job", notes = "修改job")
@RequestMapping(value = "/update", method = RequestMethod.POST)
public Response updateJob(@RequestParam(name = "jobName") String jobName,
@RequestParam(name = "jobGroup") String jobGroup,
@RequestParam(name = "cronExpression") String cronExpression) {
scheduleJobService.updateCronExpression(jobName, jobGroup, cronExpression);
return Response.success();
}
/**
* 删除job
*/
@ApiOperation(value = "删除job", notes = "删除job")
@RequestMapping(value = "/delete", method = RequestMethod.POST)
public Response deleteJob(@RequestParam(name = "jobName") String jobName,
@RequestParam(name = "jobGroup") String jobGroup) {
scheduleJobService.deleteJob(jobName, jobGroup);
return Response.success();
}
/**
* 暂停job //暂停运行和恢复运行需要批量更新任务状态
*/
@ApiOperation(value = "暂停job", notes = "暂停job")
@RequestMapping(value = "/pause", method = RequestMethod.POST)
public Response pauseJob(@RequestParam(name = "jobName") String jobName,
@RequestParam(name = "jobGroup") String jobGroup) {
scheduleJobService.pauseJob(jobName, jobGroup);
return Response.success();
}
/**
* 恢复job
*/
@ApiOperation(value = "恢复job", notes = "恢复job")
@RequestMapping(value = "/resume", method = RequestMethod.POST)
public Response resumeJob(@RequestParam(name = "jobName") String jobName,
@RequestParam(name = "jobGroup") String jobGroup) {
scheduleJobService.resumeJob(jobName, jobGroup);
return Response.success();
}
/**
* 立即执行job
*/
@ApiOperation(value = "立即执行任务", notes = "立即执行一次")
@RequestMapping(value = "/run", method = RequestMethod.POST)
public Response runJobNow(@RequestBody List<ScheduleJobEntity> jobList) {
scheduleJobService.runJobNow(jobList);
return Response.success();
}
/**
* 从数据库:查询所有计划中的任务列表分页
*/
@RequestMapping(value = "/queryScheduleJob")
public Response<Page<ScheduleJobVO>> queryScheduleAllJob(@RequestParam(name = "searchParam", required = false) String searchParam,
@RequestParam(name = "pageSize", required = false, defaultValue = "15") Integer pageSize,
@RequestParam(name = "pageNum", required = false, defaultValue = "1") Integer pageNum) {
Page<ScheduleJobVO> result = scheduleJobService.queryScheduleJob(searchParam, pageSize, pageNum);
return Response.success(result);
}
/**
* 获取所有正在运行的job
*/
@ApiOperation(value = "获取所有正在运行的job", notes = "获取所有正在运行的job")
@RequestMapping(value = "/getRunningJob", method = RequestMethod.GET)
public Response getRunningJob() throws SchedulerException {
List<ScheduleJobVO> result = scheduleJobService.getRunningJob();
return Response.success(result);
}
/**
* 获取所有计划中的任务列表
*/
@ApiOperation(value = "获取所有计划中的任务列表", notes = "获取所有计划中的任务列表")
@RequestMapping(value = "/getAllJob", method = RequestMethod.GET)
public Response getAllJob() throws SchedulerException {
List<ScheduleJobVO> result = scheduleJobService.getAllJob();
PageInfo<ScheduleJobVO> pageInfo = new PageInfo<>(result);
return Response.success(pageInfo);
}
}
(2)定时任务执行记录日志Controller
import com.example.quartz.util.Response;
import com.example.quartz.util.Page;
import com.example.quartz.entity.vo.ScheduleJobLogVO;
import com.example.quartz.entity.vo.ScheduleJobVO;
import com.example.quartz.service.ScheduleJobLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 定时任务执行记录日志Controller
*/
@RestController
@RequestMapping(value = "/quartz/log")
public class ScheduleJobLogController {
@Autowired
private ScheduleJobLogService scheduleJobLogService;
/**
* 定时任务执行记录
*/
@RequestMapping(value = "/jobLogs")
public Response<Page<ScheduleJobLogVO>> getHistoryScheduleJobLog(@RequestParam(name = "jobName", required = false) String jobName,
@RequestParam(name = "jobGroup", required = false) String jobGroup,
@RequestParam(name = "searchParam", required = false) String searchParam,
@RequestParam(name = "pageSize", required = false, defaultValue = "15") Integer pageSize,
@RequestParam(name = "pageNum", required = false, defaultValue = "1") Integer pageNum) {
Page<ScheduleJobLogVO> result = scheduleJobLogService.scheduledTaskLogList(jobName, jobGroup, searchParam, pageSize, pageNum);
return Response.success(result);
}
}
(3)定时任务测试Controller
import com.example.quartz.entity.ScheduleJobEntity;
import com.example.quartz.entity.vo.ScheduleJobVO;
import com.example.quartz.mapper.ScheduleJobMapper;
import com.example.quartz.service.ScheduleJobService;
import com.example.quartz.util.Response;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
@Slf4j
@RestController
@RequestMapping(value = "/quartz/test")
public class TestScheduleJobController {
@Autowired
private ScheduleJobMapper scheduleJobMapper;
@Autowired
private ScheduleJobService scheduleJobService;
@ApiOperation(value = "测试带参数的job", notes = "测试post请求job,参数不为空")
@RequestMapping(value = "/job", method = RequestMethod.POST)
public Response testJob(@RequestBody @Valid ScheduleJobEntity scheduleJobEntity) {
String jobName = scheduleJobEntity.getJobName();
String jobGroup = scheduleJobEntity.getJobGroup();
ScheduleJobEntity scheduleJobEntityResult = scheduleJobMapper.getTaskByJobNameAndJobGroup(jobName, jobGroup);
return Response.success(scheduleJobEntityResult);
}
/**
* 获取所有计划中的任务列表
*/
@ApiOperation(value = "测试参数为空的job", notes = "测试post请求job,参数为空")
@RequestMapping(value = "/getAllJob", method = RequestMethod.POST)
public Response getAllJob() throws SchedulerException {
List<ScheduleJobVO> result = scheduleJobService.getAllJob();
PageInfo<ScheduleJobVO> pageInfo = new PageInfo<>(result);
return Response.success(pageInfo);
}
}
定时任务效果
源码下载