
文章参考
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进行定时任务的调度就可以避免这个问题。
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进行查询
因为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', ' rn{rn "jobName": "task3",rn "jobGroup": "adce"rn}', '2021-09-24 16:28:11', null);
commit;
2.引入pom依赖
3.application.properties配置org.springframework.boot spring-boot-starterorg.springframework.boot spring-boot-starter-weborg.springframework spring-context-supportorg.springframework.boot spring-boot-starter-testtest mysql mysql-connector-java5.1.46 runtime org.mybatis.spring.boot mybatis-spring-boot-starter1.3.2 org.quartz-scheduler quartz2.2.3 org.quartz-scheduler quartz-jobs2.2.3 org.apache.httpcomponents httpclient4.5.6 org.apache.commons commons-lang33.8.1 com.alibaba fastjson1.2.53 com.alibaba druid1.1.9 com.github.pagehelper pagehelper-spring-boot-starter1.2.5 org.projectlombok lombok1.18.4 io.springfox springfox-swagger22.7.0 io.springfox springfox-swagger-ui2.7.0
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
@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 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;
@Configuration
public class QuartzConfig {
@Autowired
private DataSource dataSource;
@Autowired
private JobFactory jobFactory;
@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
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;
@Component
public class JobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory beanFactory;
@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;
@Slf4j
@DisallowConcurrentExecution
public class ScheduleJob implements Job {
@Resource
private ScheduleJobLogService scheduleJobLogService;
@Override
public void execute(JobExecutionContext jobExecutionContext) {
//JobDetail jobDetail = jobExecutionContext.getJobDetail();
//Map 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);
}
}
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 {
void addJob(ScheduleJobEntity scheduleJobEntityParam);
void updateCronexpression(String jobName, String jobGroup, String cronexpression);
void deleteJob(String jobName, String jobGroup);
void pauseJob(String jobName, String jobGroup);
void resumeJob(String jobName, String jobGroup);
void runJobNow(List jobList);
Page queryScheduleJob(String searchParam, Integer pageSize, Integer pageNum);
List getRunningJob() throws SchedulerException;
List 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,从数据库读取 :{}", this);
List 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 jobList) {
for (ScheduleJobEntity scheduleJobEntity : jobList) {
JobUtil.run(scheduler, scheduleJobEntity);
}
}
@Override
public Page queryScheduleJob(String searchParam, Integer pageSize, Integer pageNum) {
Integer beginIndex = (pageNum - 1) * pageSize;
Map sqlMap = new HashMap<>();
sqlMap.put("searchParam", searchParam);
sqlMap.put("pageSize", pageSize);
sqlMap.put("beginIndex", beginIndex);
List 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 httpJobDetailVOPageVO = new Page<>();
httpJobDetailVOPageVO.setPageNum(pageNum);
httpJobDetailVOPageVO.setPageSize(pageSize);
httpJobDetailVOPageVO.setCount(scheduleJobVOList.size());
httpJobDetailVOPageVO.setTotalCount(scheduleJobMapper.queryScheduleJobCount(sqlMap));
httpJobDetailVOPageVO.setResultList(scheduleJobVOList);
return httpJobDetailVOPageVO;
}
@Override
public List getRunningJob() throws SchedulerException {
List executingJobs = scheduler.getCurrentlyExecutingJobs();
List jobList = new ArrayList(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;
}
@Override
public List getAllJob() throws SchedulerException {
GroupMatcher matcher = GroupMatcher.anyJobGroup();
Set jobKeys = scheduler.getJobKeys(matcher);
List jobList = new ArrayList();
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 scheduledTaskLogList(String jobName, String jobGroup, String searchParam, Integer pageSize, Integer pageNum);
Page 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 scheduledTaskLogList(String jobName, String jobGroup, String searchParam, Integer pageSize, Integer pageNum) {
Integer beginIndex = (pageNum - 1) * pageSize;
Map sqlMap = new HashMap<>();
sqlMap.put("jobName", jobName);
sqlMap.put("jobGroup", jobGroup);
sqlMap.put("searchParam", searchParam);
sqlMap.put("pageSize", pageSize);
sqlMap.put("beginIndex", beginIndex);
List scheduleJobLogVOList = scheduleJobLogMapper.queryscheduledTaskLog(sqlMap);
Page 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 getHistoryTaskInfoList(String searchParam, Integer pageSize, Integer pageNum) {
Integer beginIndex = (pageNum - 1) * pageSize;
Map sqlMap = new HashMap<>();
sqlMap.put("searchParam", searchParam);
sqlMap.put("pageSize", pageSize);
sqlMap.put("beginIndex", beginIndex);
List scheduleJobVOList = scheduleJobMapper.queryHistoryTaskInfoList(sqlMap);
Page 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 getAllTask();
List queryScheduleJob(Map map);
ScheduleJobEntity getTaskByJobNameAndJobGroup(@Param("jobName") String jobName, @Param("jobGroup") String jobGroup);
Integer queryScheduleJobCount(Map map);
int addJob(ScheduleJobEntity scheduleJobEntity);
List queryHistoryTaskInfoList(Map map);
Integer queryHistoryTaskInfoListCount(Map map);
Integer deletjob(@Param("jobName") String jobName, @Param("jobGroup") String jobGroup);
}
(2)定时任务执行记录mapper接口
@Repository
public interface ScheduleJobLogMapper {
int insertScheduledTaskLog(ScheduleJobLogVO scheduleJobLogVO);
List queryscheduledTaskLog(Map map);
Integer queryscheduledTaskLogCount(Map map);
}
(3)定时任务业务逻辑mapper.xml
(4)定时任务执行记录mapper.xmlID ,JOB_NAME,JOB_GROUP,DEscriptION,REQUEST_TYPE,HTTP_URL,HTTP_PARAMS,TASK_STATUS, CRON_expression, CREATE_TIME,UPDATE_TIME
定时任务用到的bean (1)定时任务entityID,JOB_ID,JOB_NAME,JOB_GROUP,DEscriptION,REQUEST_TYPE,HTTP_URL,HTTP_PARAMS,cron_expression,TASK_STATUS,times,CREATE_TIME,UPDATE_TIME insert into schedule_job_log ID, JOB_ID, JOB_NAME, JOB_GROUP, DEscriptION, REQUEST_TYPE, HTTP_URL, HTTP_PARAMS, cron_expression, TASK_STATUS, times, CREATE_TIME, UPDATE_TIME, #{id,jdbcType=BIGINT}, #{jobId,jdbcType=BIGINT}, #{jobName,jdbcType=VARCHAR}, #{jobGroup,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{requestType,jdbcType=VARCHAR}, #{httpUrl,jdbcType=VARCHAR}, #{httpParams,jdbcType=VARCHAR}, #{cronexpression,jdbcType=VARCHAR}, #{taskStatus,jdbcType=VARCHAR}, #{times,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}, SELECT FROM schedule_job_log t WHERe 1=1 AND t.JOB_NAME = #{jobName} AND t.JOB_GROUP = #{jobGroup} AND ( t.JOB_NAME LIKE concat('%',#{searchParam},'%') OR t.JOB_GROUP LIKE concat('%',#{searchParam},'%') ) ORDER BY t.ID DESClimit #{beginIndex},#{pageSize} SELECT COUNT(1) FROM schedule_job_log t WHERe 1=1 AND t.JOB_NAME = #{jobName} AND t.JOB_GROUP = #{jobGroup} AND ( t.JOB_NAME LIKE concat('%',#{searchParam},'%') OR t.JOB_GROUP LIKE concat('%',#{searchParam},'%') )
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class ScheduleJobEntity implements Serializable {
private static final long serialVersionUID = -50190044894125802L;
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
private Long jobId;
private String jobName;
private String jobGroup;
private String description;
private String requestType;
private String httpUrl;
private String httpParams;
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 {
private Long jobId;
private String jobName;
private String jobGroup;
private String description;
private String requestType;
private String httpUrl;
private String httpParams;
private String cronexpression;
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;
private Long id;
private Long jobId;
private String jobName;
private String jobGroup;
private String description;
private String requestType;
private String httpUrl;
private String httpParams;
private String cronexpression;
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;
@NotEmpty(message = "请求URL不能为空")
private String httpUrl;
private String httpParams;
@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_";
public static TriggerKey getTriggerKey(Long jobId) {
return TriggerKey.triggerKey(JOB_NAME + jobId);
}
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);
}
public static JobKey getJobKey(Long jobId) {
return JobKey.jobKey(JOB_NAME + jobId);
}
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);
}
}
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);
}
}
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;
public class HttpClientUtil {
public static final int HTTP_CONNECT_TIMEOUT_30S = 30 * 1000;
public static final int HTTP_READ_TIMEOUT_3MIN = 180 * 1000;
public static final int HTTP_SUCCESS_STATUS_CODE = 200;
private static final Logger logger = LogManager.getLogger(HttpClientUtil.class);
private HttpClientUtil() {
}
public static String sendGetRequestMap(String url, Map 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 formParams = new ArrayList<>();
for (Entry 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;
}
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 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;
}
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;
}
public static String sendPostRequestMap(String url, Map 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 formParams = new ArrayList<>();
for (Entry 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(4)返回结果封装工具类{ private Integer pageNum; private Integer pageSize; private Integer count; private Integer pageCount; private Integer totalCount; private List 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 getResultList() { return resultList; } public void setResultList(List resultList) { this.resultList = resultList; } }
import com.example.quartz.enu.ResultEnum; import java.io.Serializable; public class Response(5)JSON参数格式校验工具类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 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; } }
import com.alibaba.fastjson.JSONObject;
public class JsonValidUtil {
public static boolean isJson(String jsonStr) {
try {
JSONObject.parseObject(jsonStr);
return true;
} catch (Exception e) {
return false;
}
}
}
定时任务常量类和枚举
(1)定时任务常量类
public class Constant {
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";
public static final String POST_JSON = "POST_JSON";
public static final String POST_FORM_DATA = "POST_FORM";
public static final String GET = "GET";
public static final String JOB_STATUS_NORMAL = "NORMAL";
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;
@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();
}
@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();
}
@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();
}
@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();
}
@ApiOperation(value = "立即执行任务", notes = "立即执行一次")
@RequestMapping(value = "/run", method = RequestMethod.POST)
public Response runJobNow(@RequestBody List jobList) {
scheduleJobService.runJobNow(jobList);
return Response.success();
}
@RequestMapping(value = "/queryScheduleJob")
public Response> 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 result = scheduleJobService.queryScheduleJob(searchParam, pageSize, pageNum);
return Response.success(result);
}
@ApiOperation(value = "获取所有正在运行的job", notes = "获取所有正在运行的job")
@RequestMapping(value = "/getRunningJob", method = RequestMethod.GET)
public Response getRunningJob() throws SchedulerException {
List result = scheduleJobService.getRunningJob();
return Response.success(result);
}
@ApiOperation(value = "获取所有计划中的任务列表", notes = "获取所有计划中的任务列表")
@RequestMapping(value = "/getAllJob", method = RequestMethod.GET)
public Response getAllJob() throws SchedulerException {
List result = scheduleJobService.getAllJob();
PageInfo 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;
@RestController
@RequestMapping(value = "/quartz/log")
public class ScheduleJobLogController {
@Autowired
private ScheduleJobLogService scheduleJobLogService;
@RequestMapping(value = "/jobLogs")
public Response> 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 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 result = scheduleJobService.getAllJob();
PageInfo pageInfo = new PageInfo<>(result);
return Response.success(pageInfo);
}
}
定时任务效果
源码下载
https://github.com/helloflygit/springboot-quartz