栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot集成Quartz数据库配置定时任务

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot集成Quartz数据库配置定时任务

文章参考

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', '	rn{rn  "jobName": "task3",rn  "jobGroup": "adce"rn}', '2021-09-24 16:28:11', null);


commit;
2.引入pom依赖


        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework
            spring-context-support
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
            mysql
            mysql-connector-java
            5.1.46
            runtime
        

        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            1.3.2
        

        
        
            org.quartz-scheduler
            quartz
            2.2.3
        
        
            org.quartz-scheduler
            quartz-jobs
            2.2.3
        

        
        
            org.apache.httpcomponents
            httpclient
            4.5.6
        

        
        
            org.apache.commons
            commons-lang3
            3.8.1
        

        
        
            com.alibaba
            fastjson
            1.2.53
        

        
        
            com.alibaba
            druid
            1.1.9
        
        
            com.github.pagehelper
            pagehelper-spring-boot-starter
            1.2.5
        
        
            org.projectlombok
            lombok
            1.18.4
        

        
            io.springfox
            springfox-swagger2
            2.7.0
        
        
            io.springfox
            springfox-swagger-ui
            2.7.0
        
    
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
@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 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




    
        
        
        
        
        
        
        
        
        
        
    

    
        ID
        ,JOB_NAME,JOB_GROUP,DEscriptION,REQUEST_TYPE,HTTP_URL,HTTP_PARAMS,TASK_STATUS, CRON_expression, CREATE_TIME,UPDATE_TIME
    

    
        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

    

    
        insert into schedule_job
        
            
                ID,
            
            
                JOB_NAME,
            
            
                JOB_GROUP,
            
            
                DEscriptION,
            
            
                REQUEST_TYPE,
            
            
                HTTP_URL,
            
            
                HTTP_PARAMS,
            
            
                CRON_expression,
            
            
                TASK_STATUS,
            
        
        
            
                #{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},
            
        
    

    
        
        
        
        
        
        
        
        
        
        
        
    

    
        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
        
            AND ( t.JOB_NAME LIKE concat('%',#{searchParam},'%') OR t.JOB_GROUP LIKE concat('%',#{searchParam},'%') )
        
    

    
        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)
        
            AND ( hd.JOB_NAME LIKE concat('%',#{searchParam},'%') OR hd.JOB_GROUP LIKE concat('%',#{searchParam},'%') )
        
    


    
        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 DESC
        
            limit #{beginIndex},#{pageSize}
        
    

    

定时任务用到的bean (1)定时任务entity

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 {

    
    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;
    }
}
(4)返回结果封装工具类
import com.example.quartz.enu.ResultEnum;

import java.io.Serializable;



public class Response 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;
    }
}

(5)JSON参数格式校验工具类
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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/273914.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号