Springcloud学习笔记43--任务调度框架Quartz 使用02

1.pom 依赖配置和生成数据库表

1.1 pom 依赖配置

复制代码
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.3.16</version>
        </dependency>
复制代码

1.2 生成quartz相关的数据库表

在数据库中添加quartz相关表

共11张表,前6张都是关于各种triggers的信息,后面包括job,悲观锁,调度状态等信息;相关表操作在类StdJDBCDelegate中,相关sql语句在StdJDBCConstants中;

(1) qrtz_blob_triggers

自定义的triggers使用blob类型进行存储,非自定义的triggers不会存放在此表中,Quartz提供的triggers包括:CronTrigger,CalendarIntervalTrigger,

DailyTimeIntervalTrigger以及SimpleTrigger,这几个trigger信息会保存在后面的几张表中;

(2)qrtz_cron_triggers

存储CronTrigger,这也是我们使用最多的触发器,在配置文件中做如下配置,即可在qrtz_cron_triggers生成记录:

(3)qrtz_simple_triggers

存储SimpleTrigger,在配置文件中做如下配置,即可在qrtz_simple_triggers生成记录:

(4)qrtz_simprop_triggers

存储CalendarIntervalTrigger和DailyTimeIntervalTrigger两种类型的触发器,使用CalendarIntervalTrigger做如下配置:

CalendarIntervalTrigger没有对应的FactoryBean,直接设置实现类CalendarIntervalTriggerImpl;指定的重复周期是1,默认单位是天,也就是每天执行一次,查看表如下:提供了3个string类型的参数,2个int类型的参数,2个long类型的参数,2个decimal类型的参数以及2个boolean类型的参数;具体每个参数是什么含义,根据不同的trigger类型存放各自的参数;

(5)qrtz_fired_triggers

存储已经触发的trigger相关信息,trigger随着时间的推移状态发生变化,直到最后trigger执行完成,从表中被删除;已SimpleTrigger为例重复3次执行,查询表:

(6)qrtz_triggers

触发器的基本信息

(7)qrtz_job_details

存储jobDetails信息,相关信息在定义的时候指定,如上面定义的JobDetailFactoryBean,查询数据库:

JOB_DATA存放的就是定义task时指定的jobDataMap属性,所以此属性需要实现Serializable接口,方便持久化到数据库;

(8)qrtz_calendars

Quartz为我们提供了日历的功能,可以自己定义一个时间段,可以控制触发器在这个时间段内触发或者不触发;现在提供6种类型:AnnualCalendar,CronCalendar,DailyCalendar,HolidayCalendar,MonthlyCalendar,WeeklyCalendar;

(9)qrtz_paused_trigger_grps

存放暂停掉的触发器,测试手动暂停firstCronTrigger

(10)qrtz_scheduler_state

存储所有节点的scheduler,会定期检查scheduler是否失效,启动多个scheduler,查询数据库:

记录了最后最新的检查时间,在quartz.properties中设置了CHECKIN_INTERVAL为1000,也就是每秒检查一次;

(11)qrtz_locks

Quartz提供的锁表,为多个节点调度提供分布式锁,实现分布式调度,默认有2个锁:

复制代码
#
# In your Quartz properties file, you'll need to set 
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#
#
# By: Ron Cordell - roncordell
#  I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(120) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
  (          
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    STR_PROP_1 VARCHAR(512) NULL,
    STR_PROP_2 VARCHAR(512) NULL,
    STR_PROP_3 VARCHAR(512) NULL,
    INT_PROP_1 INT NULL,
    INT_PROP_2 INT NULL,
    LONG_PROP_1 BIGINT NULL,
    LONG_PROP_2 BIGINT NULL,
    DEC_PROP_1 NUMERIC(13,4) NULL,
    DEC_PROP_2 NUMERIC(13,4) NULL,
    BOOL_PROP_1 VARCHAR(1) NULL,
    BOOL_PROP_2 VARCHAR(1) NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB;
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
commit; 
复制代码

2.注册Quartz 任务(Job) 工厂和注册调度工厂

2.1 注册Quartz 任务(Job) 工厂

复制代码
package com.ttbank.flep.config;

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;

/**
 * @Author lucky
 * @Date 2022/4/1 15:50
 * 注册Quartz 任务(Job) 工厂
 */
@Component
public class QuartzJobFactory extends AdaptableJobFactory {
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory; //AutowireCapableBeanFactory提供了自动装配Bean的实现,提供bean创建(带有构造函数解析)、属性填充、连接(包括自动装配)和初始化

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}
复制代码

2.2 配置数据库连接池

(1)读取yaml文件中的配置项

复制代码
package com.ttbank.flep.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @Author lucky
 * @Date 2022/3/31 10:22
 */
@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource.druid")
public class DataSourceProperties {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private int initialSize;
    private int minIdle;
    private int maxActive=100;
    private long maxWait;
    private long timeBetweenEvictionRunsMillis;
    private long minEvictableIdleTimeMillis;
    private String validationQuery;
    private boolean testWhileIdle;
    private boolean testOnBorrow;
    private boolean testOnReturn;

}
复制代码

(2)配置数据库连接池,注入DataSource

复制代码
package com.ttbank.flep.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.sql.SQLException;

/**
 * @Author lucky
 * @Date 2022/4/1 9:18
 * 配置数据库连接池,注入DataSource
 */
@Configuration
public class DruidConfig {
    @Autowired
    private DataSourceProperties dataSourceProperties;

    @Bean
    public DataSource druidDataSource(){
        DruidDataSource druidDataSource=new DruidDataSource();
        druidDataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
        druidDataSource.setUrl(dataSourceProperties.getUrl());
        druidDataSource.setUsername(dataSourceProperties.getUsername());
        druidDataSource.setPassword(dataSourceProperties.getPassword());
        druidDataSource.setInitialSize(dataSourceProperties.getInitialSize());
        druidDataSource.setMinIdle(dataSourceProperties.getMinIdle());
        druidDataSource.setMaxActive(dataSourceProperties.getMaxActive());
        druidDataSource.setMaxWait(dataSourceProperties.getMaxWait());
        druidDataSource.setTimeBetweenEvictionRunsMillis(dataSourceProperties.getTimeBetweenEvictionRunsMillis());
        druidDataSource.setMinEvictableIdleTimeMillis(dataSourceProperties.getMinEvictableIdleTimeMillis());
        druidDataSource.setValidationQuery(dataSourceProperties.getValidationQuery());
        druidDataSource.setTestWhileIdle(dataSourceProperties.isTestWhileIdle());
        druidDataSource.setTestOnBorrow(dataSourceProperties.isTestOnBorrow());
        druidDataSource.setTestOnReturn(dataSourceProperties.isTestOnReturn());

        try {
            druidDataSource.init();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return druidDataSource;
    }

}
复制代码

2.3 注册调度工厂

复制代码
package com.ttbank.flep.config;

import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.LocalDataSourceJobStore;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.sql.DataSource;
import java.io.IOException;

/**
 * @Author lucky
 * @Date 2022/4/1 16:23
 * 注册调度工厂
 */
@Configuration
public class QuartzConfig {
    @Autowired
    private QuartzJobFactory jobFactory;

    @Autowired
    private DataSource dataSource;

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException{
        //01 获取配置属性
        PropertiesFactoryBean propertiesFactoryBean=new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        //在quartz.properties中的属性被读取并注入后再初始化对象;
        propertiesFactoryBean.afterPropertiesSet();
        //02 创建SchedulerFactoryBean
        SchedulerFactoryBean factory=new SchedulerFactoryBean();
        factory.setQuartzProperties(propertiesFactoryBean.getObject());
        factory.setJobFactory(jobFactory);
        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
        //当spring关闭时,会等待所有已经启动的quartz job结束后才能完全shutdown
        factory.setWaitForJobsToCompleteOnShutdown(true);
        //是否覆盖已经存在的JOB
        factory.setOverwriteExistingJobs(false);
        factory.setStartupDelay(10);
        factory.setDataSource(dataSource);
        return factory;


    }

    @Bean(name="scheduler")
    public Scheduler scheduler() throws IOException{
        Scheduler scheduler = schedulerFactoryBean().getScheduler();
        return scheduler;
    }

}
复制代码

3.controller

复制代码
package com.ttbank.flep.controller;

import com.ttbank.flep.service.QuartzService;
import dto.AppQuartzDTO;
import dto.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @Author lucky
 * @Date 2022/4/1 17:50
 */
@RestController
@RequestMapping("/quartztest")
public class QuartzController {
    @Autowired
    QuartzService quartzService;

    /**
     * 添加任务
     */
    @PostMapping("/addJob")
    public Result addJob(@RequestBody AppQuartzDTO appQuartzDTO){
        quartzService.addJob(appQuartzDTO);
        return Result.success();
    }

    /**
     * 暂停任务
     */
    @PostMapping("/pauseJob")
    public Result pauseJob(@RequestParam String jobName,@RequestParam String jobGroupName){
        quartzService.pauseJob(jobName,jobGroupName);
        return Result.success();
    }

    /**
     * 恢复任务
     */
    @PostMapping("/resumeJob")
    public Result resumeJob(@RequestParam String jobName,@RequestParam String jobGroupName){
        quartzService.resumeJob(jobName,jobGroupName);
        return Result.success();
    }

    /**
     * 添加任务
     */
    @PostMapping("/modifyJob")
    public void modifyJob(@RequestBody AppQuartzDTO appQuartzDTO){
        quartzService.modifyJob(appQuartzDTO);
    }



}
复制代码

4.Service

(1)QuartzService接口

复制代码
package com.ttbank.flep.service;

import dto.AppQuartzDTO;

/**
 * @Author lucky
 * @Date 2022/4/2 11:49
 */
public interface QuartzService {
    /**
     * 新建任务
     * @param appQuartzDTO
     */
    void addJob(AppQuartzDTO appQuartzDTO);

    /**
     * 暂停任务
     * @param jobName
     * @param jobGroupName
     */
    void pauseJob(String jobName,String jobGroupName);

    /**
     * 恢复任务
     * @param jobName
     * @param jobGroupName
     */
    void resumeJob(String jobName, String jobGroupName);

    /**
     * 修改任务
     * @param appQuartzDTO
     */
    void modifyJob(AppQuartzDTO appQuartzDTO);
}
复制代码

(2) QuartzServiceImpl

复制代码
package com.ttbank.flep.service.impl;

import com.ttbank.flep.constant.QuartzJobDataKey;
import com.ttbank.flep.job.BaseJob;
import com.ttbank.flep.service.QuartzService;
import dto.AppQuartzDTO;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

/**
 * @Author lucky
 * @Date 2022/4/2 15:34
 */
@Slf4j
@Service
public class QuartzServiceImpl implements QuartzService {
    @Autowired
    @Qualifier("scheduler")
    private Scheduler scheduler;

    @PostConstruct
    public void startScheduler(){
        try {
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void addJob(AppQuartzDTO appQuartzDTO) {
        try {
            //01 构建job信息;
            JobDetail jobDetail = JobBuilder.newJob(getClass(appQuartzDTO.getClassName().trim()).getClass())
                    .withIdentity(appQuartzDTO.getJobName(), appQuartzDTO.getJobGroup())
                    .build();
            //02 表达式调度构建器(任务执行的时间)
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(appQuartzDTO.getCronExpression());
            //03 按新的CronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(appQuartzDTO.getJobName(), appQuartzDTO.getJobGroup())
                    .withSchedule(cronScheduleBuilder)
                    .build();
            //04 获得JobDataMap,写入数据
            fillJobDataMap(trigger.getJobDataMap(),appQuartzDTO );
            scheduler.scheduleJob(jobDetail,trigger);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void pauseJob(String jobName, String jobGroupName) {
        try {
            scheduler.pauseJob(JobKey.jobKey(jobName,jobGroupName));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void resumeJob(String jobName, String jobGroupName) {
        try {
            scheduler.resumeJob(JobKey.jobKey(jobName,jobGroupName));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void modifyJob(AppQuartzDTO appQuartzDTO) {
        try {
            //01 根据任务名和任务组获取触发器Trigger
            TriggerKey triggerKey = TriggerKey.triggerKey(appQuartzDTO.getJobName(), appQuartzDTO.getJobGroup());
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            //02 表达式调度构建器
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(appQuartzDTO.getCronExpression());
            //03 按照新的CronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder()
                    .withIdentity(triggerKey)
                    .withSchedule(cronScheduleBuilder)
                    .build();
            //04 获得JobDataMap,写入数据
            fillJobDataMap(trigger.getJobDataMap(),appQuartzDTO );
            //05 按照新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey,trigger );

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void fillJobDataMap(JobDataMap jobDataMap,AppQuartzDTO appQuartzDTO){
        jobDataMap.put(QuartzJobDataKey.CLASS_NAME,appQuartzDTO.getClassName() );
        jobDataMap.put(QuartzJobDataKey.METHOD_NAME,appQuartzDTO.getMethodName() );
        jobDataMap.put(QuartzJobDataKey.PARAMS,appQuartzDTO.getParams() );
        jobDataMap.put(QuartzJobDataKey.CRON_EXPRESS,appQuartzDTO.getCronExpression() );
    }

    /**
     * 根据类名称,通过反射得到该类;
     * @param classname
     * @throws Exception
     */
    private static BaseJob getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (BaseJob) class1.newInstance();
    }


}
复制代码

5. Job 任务

(1)BaseJob

复制代码
package com.ttbank.flep.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 * @Author lucky
 * @Date 2022/4/6 9:27
 */
public interface BaseJob extends Job {
    /**
     * 任务具体执行方法
     * @param jobExecutionContext
     * @throws JobExecutionException
     */
    @Override
    void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException;
}
复制代码

(2)ExecSdkJob

复制代码
package com.ttbank.flep.job;

import com.sun.media.jfxmedia.logging.Logger;
import com.ttbank.flep.constant.QuartzJobDataKey;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;

import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @Author lucky
 * @Date 2022/4/6 10:12
 */
@Slf4j
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class ExecSdkJob implements BaseJob {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            JobDataMap jobDataMap = context.getTrigger().getJobDataMap();
            String params = jobDataMap.getString(QuartzJobDataKey.PARAMS);

            log.info(params);
            FileOutputStream fileOutputStream=new FileOutputStream("D:\\data\\quartz_test01.txt",true);
            LocalDateTime localDateTime=LocalDateTime.now();
            String currentTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh-mm-ss"));
            fileOutputStream.write(("当前时间为:"+currentTime+"\n").getBytes());
            fileOutputStream.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
复制代码

 

posted @   雨后观山色  阅读(773)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2019-04-07 Navicat使用笔记02---Navicat 连接腾讯云
点击右上角即可分享
微信分享提示