前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springboot quartz定时任务调度

springboot quartz定时任务调度

作者头像
山行AI
发布2019-08-30 22:22:49
1.9K0
发布2019-08-30 22:22:49
举报
文章被收录于专栏:山行AI山行AI

几种任务调度

  • Timer,简单无门槛,一般也没人用。
  • ScheduledExecutorService主要用于一些单进程的简单的任务调度。
  • spring @Scheduled注解,一般集成于项目中,小任务很方便。
  • 开源工具 Quartz,分布式集群开源工具,以下两个分布式任务应该都是基于Quartz实现的,可以说是中小型公司必选,当然也视自身需求而定。
  • 分布式任务 XXL-JOB,是一个轻量级分布式任务调度框架,支持通过 Web 页面对任务进行 CRUD 操作,支持动态修改任务状态、暂停/恢复任务,以及终止运行中任务,支持在线配置调度任务入参和在线查看调度结果。
  • 分布式任务 Elastic-Job,是一个分布式调度解决方案,由两个相互独立的子项目 Elastic-Job-Lite 和 Elastic-Job-Cloud 组成。定位为轻量级无中心化解决方案,使用 jar 包的形式提供分布式任务的协调服务。支持分布式调度协调、弹性扩容缩容、失效转移、错过执行作业重触发、并行调度、自诊。
  • 分布式任务 Saturn,Saturn是唯品会在github开源的一款分布式任务调度产品。它是基于当当elastic-job来开发的,其上完善了一些功能和添加了一些新的feature。目前在github上开源大半年,470个star。Saturn的任务可以用多种语言开发比如python、Go、Shell、Java、Php。其在唯品会内部已经发部署350+个节点,每天任务调度4000多万次。同时,管理和统计也是它的亮点。

quartz

springboot 1.0时代

引入依赖

代码语言:javascript
复制
<!--quartz相关依赖--><dependency>    <groupId>org.quartz-scheduler</groupId>    <artifactId>quartz</artifactId>    <version>${quartz.version}</version></dependency><dependency>    <groupId>org.quartz-scheduler</groupId>    <artifactId>quartz-jobs</artifactId>    <version>${quartz.version}</version></dependency>

配置

配置类
代码语言:javascript
复制
@Configurationpublic class JobScheduleConfig {    @Autowired    private ApplicationContext applicationContext;    @Bean    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {        SchedulerFactoryBean factory = new SchedulerFactoryBean();        factory.setOverwriteExistingJobs(true);        factory.setAutoStartup(true);        //设置线程池        factory.setTaskExecutor(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2,                new ThreadFactoryBuilder().setNameFormat("job-schedule-factory-thread-%d").build()));        // factory.setQuartzProperties(quartzProperties());        AutoWiringSpringBeanJobFactory jobFactory = new AutoWiringSpringBeanJobFactory();        jobFactory.setApplicationContext(applicationContext);        factory.setJobFactory(jobFactory);        return factory;    }
factory类
代码语言:javascript
复制
public final class AutoWiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {    private transient AutowireCapableBeanFactory beanFactory;    @Override    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {        beanFactory = applicationContext.getAutowireCapableBeanFactory();    }    @Override    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {        final Object job = super.createJobInstance(bundle);        beanFactory.autowireBean(job);        return job;    }}
job factory
代码语言:javascript
复制
@Componentpublic class SchedulerJobFactory {    public JobDetailFactoryBean job(Class<? extends QuartzJobBean> jobClass, JobDataMap jobMap, String jobName) {        JobDetailFactoryBean jBean = createJobDetail(jobClass);        jBean.setJobDataMap(jobMap);        jBean.setBeanName(jobName);        jBean.afterPropertiesSet();        return jBean;    }    private JobDetailFactoryBean createJobDetail(Class<? extends QuartzJobBean> jobClass) {        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();        factoryBean.setJobClass(jobClass);        factoryBean.setDurability(true);        factoryBean.setRequestsRecovery(true);        factoryBean.setBeanName(jobClass.getName());        return factoryBean;    }}
trigger factory
代码语言:javascript
复制
@Componentpublic class SchedulerTriggerFactory {    public CronTriggerFactoryBean jobTrigger(JobDetail jobDetail, String frequency, String triggerName) throws ParseException {        CronTriggerFactoryBean tBean = createCronTrigger(jobDetail, frequency);        tBean.setBeanName(triggerName);        tBean.afterPropertiesSet();        return tBean;    }    private CronTriggerFactoryBean createCronTrigger(JobDetail jobDetail, String cronExpression) {        CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();        factoryBean.setJobDetail(jobDetail);        factoryBean.setCronExpression(cronExpression);        factoryBean.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW);        return factoryBean;    }}
service:
代码语言:javascript
复制
@Servicepublic class SchedulerJobService {    private static final Logger LOGGER = LoggerFactory.getLogger(SchedulerJobService.class);    @Autowired    private SchedulerFactoryBean schedulerFactoryBean;    @Autowired    private SchedulerJobFactory schedulerJobFactory;    @Autowired    private SchedulerTriggerFactory schedulerTriggerFactory;    @Resource    private ApplicationContext applicationContext;    @PostConstruct    public void setupJobs() throws ParseException, SchedulerException {        Map<String, AStandardBaseJob> beanMap = BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext,                AStandardBaseJob.class);        LOGGER.info("【task扫描注册已启动】-共找到task数为[{}]", beanMap != null ? beanMap.size() : 0);        beanMap.keySet().forEach(key -> {            AStandardBaseJob aStandardBaseJob = beanMap.get(key);            String className = aStandardBaseJob.getClass().getName();            LOGGER.info("[------------扫描到的任务的名称为:" + className + "----------------------]");        });        if (beanMap != null && beanMap.size() > 0) {            beanMap.forEach((key, value) -> {                if (!this.baseCheck(value)) {                    return;                }                try {                    scheduleJob(value.getClass(), null, value.initCronValue(), StringBuilderHolder.getGlobal().                                    append(value.initAppId()).append("-").append(value.initCronKey()).toString(),                            value.initCronKey());                } catch (ParseException e) {                    e.printStackTrace();                } catch (SchedulerException e) {                    e.printStackTrace();                }            });        }        // scheduleJob(ContentStatisticsJob.class, null, "1/1 * * * * ?",        // "exampleJob", "trigger1");    }    public Date scheduleJob(Class<? extends QuartzJobBean> object, JobDataMap jMap, String frequency, String jobName,                            String triggerName) throws ParseException, SchedulerException {        JobDetailFactoryBean jobDetailFactoryBean = schedulerJobFactory.job(object, jMap, jobName);        CronTriggerFactoryBean cronTriggerFactoryBean = schedulerTriggerFactory                .jobTrigger(jobDetailFactoryBean.getObject(), frequency, triggerName);        return schedulerFactoryBean.getScheduler().scheduleJob(jobDetailFactoryBean.getObject(),                cronTriggerFactoryBean.getObject());    }    /**     * 基本校验     *     * @Description     * @param aTaskStandardJob     * @return     */    public boolean baseCheck(AStandardBaseJob aTaskStandardJob) {        if (StringUtils.isBlank(aTaskStandardJob.initAppId())) {            LOGGER.error("【task扫描注册出现异常】-类[{}]-[appId]-不能为空", aTaskStandardJob.getClass());            return false;        }        if (StringUtils.isBlank(aTaskStandardJob.initCronKey())) {            LOGGER.error("【task扫描注册出现异常】-类[{}]-[CronKey]-不能为空", aTaskStandardJob.getClass());            return false;        }        if (StringUtils.isBlank(aTaskStandardJob.initCronValue())) {            LOGGER.error("【task扫描注册出现异常】-类[{}]-[CronValue]-不能为空", aTaskStandardJob.getClass());            return false;        }        if (aTaskStandardJob.initValidSign() == BaseGlobalConstants.VALID_SIGN_N) {            LOGGER.info("【task扫描注册】-类[{}]-[valid_sign]-为无效", aTaskStandardJob.getClass());            return false;        }        return true;    }}
通用job:
代码语言:javascript
复制
public abstract class AStandardBaseJob extends QuartzJobBean{    /**     * 初始化appid     *     * @Description     * @return appId     */    public abstract String initAppId();    /**     * 初始化Cron表达式key     *     * @Description     * @return cronKey     */    public abstract String initCronKey();    /**     * 初始化Cron表达式值     *     * @Description     * @return 表达式值     */    public abstract String initCronValue();    /**     * 初始化有效标志     *     * @Description     * @return 表达式值     */    public abstract int initValidSign();}

springboot 2.0时代

引入依赖

代码语言:javascript
复制
<!--quartz依赖--><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-quartz</artifactId></dependency>

在我们添加spring-boot-starter-quartz依赖后就不需要主动声明工厂类,因为spring-boot-starter-quartz已经为我们自动化配置好了。展开spring-boot-autoconfigure-2.0.0.RELEASE.jar,找到org.springframework.boot.autoconfigure.quartz,该目录就是SpringBoot为我们提供的Quartz自动化配置源码实现,在该目录下有如下所示几个类:

  • AutowireCapableBeanJobFactory 该类替代了我们之前在QuartzConfiguration配置类的AutowiringSpringBeanJobFactory内部类实现,主要作用是我们自定义的QuartzJobBean子类被Spring IOC进行托管,可以在定时任务类内使用注入任意被Spring IOC托管的类。
  • JobStoreType 该类是一个枚举类型,定义了对应application.yml、application.properties文件内spring.quartz.job-store-type配置,其目的是配置quartz任务的数据存储方式,分别为:MEMORY(内存方式:默认)、JDBC(数据库方式)。
  • QuartzAutoConfiguration 该类是自动配置的主类,内部配置了SchedulerFactoryBean以及JdbcStoreTypeConfiguration,使用QuartzProperties作为属性自动化配置条件。
  • QuartzDataSourceInitializer 该类主要用于数据源初始化后的一些操作,根据不同平台类型的数据库进行选择不同的数据库脚本。
  • QuartzProperties 该类对应了spring.quartz在application.yml、application.properties文件内开头的相关配置。
  • SchedulerFactoryBeanCustomizer 这是一个接口,我们实现该接口后并且将实现类使用Spring IOC托管,可以完成SchedulerFactoryBean的个性化设置,这里的设置完全可以对SchedulerFactoryBean做出全部的设置变更。
  • spring.quartz.properties 该配置其实代替了之前的quartz.properties,我们把之前quartz.properties配置文件内的所有配置转换成YAML风格,对应的添加在该配置下即可,在QuartzAutoConfiguration类内,会自动调用SchedulerFactoryBean的setQuartzProperties方法,把spring.quartz.properties内的所有配置进行设置。

实战

表说明

代码语言:javascript
复制
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* 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;
*/

说明:

  • QRTZ_CALENDARS 以 Blob 类型存储 Quartz 的 Calendar 信息
  • QRTZCRONTRIGGERS 存储 Cron Trigger,包括 Cron表达式和时区信息
  • QRTZFIREDTRIGGERS 存储与已触发的 Trigger 相关的状态信息,以及相联 Job的执行信息 QRTZPAUSEDTRIGGER_GRPS 存储已暂停的 Trigger 组的信息
  • QRTZSCHEDULERSTATE 存储少量的有关 Scheduler 的状态信息,和别的 Scheduler实例(假如是用于一个集群中)
  • QRTZ_LOCKS 存储程序的悲观锁的信息(假如使用了悲观锁)
  • QRTZJOBDETAILS 存储每一个已配置的 Job 的详细信息
  • QRTZJOBLISTENERS 存储有关已配置的 JobListener 的信息
  • QRTZSIMPLETRIGGERS 存储简单的Trigger,包括重复次数,间隔,以及已触的次数
  • QRTZBLOGTRIGGERS Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候)
  • QRTZTRIGGERLISTENERS 存储已配置的 TriggerListener 的信息
  • QRTZ_TRIGGERS 存储已配置的 Trigger 的信息

表字段说明:

代码语言:javascript
复制
表qrtz_job_details: 保存job详细信息,该表需要用户根据实际情况初始化job_name:集群中job的名字,该名字用户自己可以随意定制,无强行要求job_group:集群中job的所属组的名字,该名字用户自己随意定制,无强行要求job_class_name:集群中个note job实现类的完全包名,quartz就是根据这个路径到classpath找到该job类is_durable:是否持久化,把该属性设置为1,quartz会把job持久化到数据库中job_data:一个blob字段,存放持久化job对象表qrtz_triggers: 保存trigger信息trigger_name: trigger的名字,该名字用户自己可以随意定制,无强行要求trigger_group:trigger所属组的名字,该名字用户自己随意定制,无强行要求job_name: qrtz_job_details表job_name的外键job_group: qrtz_job_details表job_group的外键trigger_state:当前trigger状态,设置为ACQUIRED,如果设置为WAITING,则job不会触发;暂停任务时状态为PAUSEDtrigger_cron:触发器类型,使用cron表达式表qrtz_cron_triggers:存储cron表达式表trigger_name: qrtz_triggers表trigger_name的外键trigger_group: qrtz_triggers表trigger_group的外键cron_expression:cron表达式表qrtz_scheduler_state:存储集群中note实例信息,quartz会定时读取该表的信息判断集群中每个实例的当前状态instance_name:之前配置文件中org.quartz.scheduler.instanceId配置的名字,就会写入该字段,如果设置为AUTO,quartz会根据物理机名和当前时间产生一个名字last_checkin_time:上次检查时间checkin_interval:检查间隔时间

springboot 配置说明

代码语言:javascript
复制
spring.quartz.properties.org.quartz.scheduler.instanceName = clusteredSchedulerspring.quartz.properties.org.quartz.scheduler.instanceId = AUTOspring.quartz.properties.org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTXspring.quartz.properties.org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegatespring.quartz.properties.org.quartz.jobStore.tablePrefix = qrtz_spring.quartz.properties.org.quartz.jobStore.isClustered = truespring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval = 10000spring.quartz.properties.org.quartz.jobStore.useProperties = falsespring.quartz.properties.org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPoolspring.quartz.properties.org.quartz.threadPool.threadCount = 2spring.quartz.properties.org.quartz.threadPool.threadPriority = 2spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = truespring.quartz.job-store-type = jdbcspring.quartz.startup-delay=5sspring.quartz.jdbc.initialize-schema=neverspring.quartz.overwrite-existing-jobs=false

执行定时任务

代码语言:javascript
复制
@Componentpublic class TaskRunner implements ApplicationRunner {    private final static Logger LOGGER = LoggerFactory.getLogger(TaskRunner.class);    @Autowired    private IQrtzJobDetailsService jobService;    @Autowired    private Scheduler scheduler;    @SuppressWarnings({ "rawtypes", "unchecked" })    @Override    public void run(ApplicationArguments var) throws Exception{        Long count = jobService.countQuartzEntity();        if(count==0){            LOGGER.info("初始化测试任务");            QuartzEntity quartz = new QuartzEntity();            quartz.setJobName("test01");            quartz.setJobGroup("test");            quartz.setDescription("测试任务");            quartz.setJobClassName("com.ambition.common.quartz.job.TestJob");            quartz.setCronExpression("0/20 * * * * ?");               Class cls = Class.forName(quartz.getJobClassName()) ;               cls.newInstance();               //构建job信息               JobDetail job = JobBuilder.newJob(cls).withIdentity(quartz.getJobName(),                       quartz.getJobGroup())                       .withDescription(quartz.getDescription()).build();               // 触发时间点               CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression());               Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger"+quartz.getJobName(), quartz.getJobGroup())                       .startNow().withSchedule(cronScheduleBuilder).build();                 //交由Scheduler安排触发               scheduler.scheduleJob(job, trigger);        }    }}

任务类:

代码语言:javascript
复制
/** * 实现序列化接口、防止重启应用出现quartz Couldn't retrieve job because a required class was not found 的问题 * * Job 的实例要到该执行它们的时候才会实例化出来。每次 Job 被执行,一个新的 Job 实例会被创建。 * 其中暗含的意思就是你的 Job 不必担心线程安全性,因为同一时刻仅有一个线程去执行给定 Job 类的实例,甚至是并发执行同一 Job 也是如此。 * @DisallowConcurrentExecution 保证上一个任务执行完后,再去执行下一个任务,这里的任务是同一个任务 */@DisallowConcurrentExecutionpublic class TestJob implements Job,Serializable {    private static final long serialVersionUID = 1L;    @Override    public void execute(JobExecutionContext context) throws JobExecutionException {        System.out.println("任务执行成功");    }}

controller类:

代码语言:javascript
复制
@Api(tags ="Quartz任务")@RestController@RequestMapping("/job")public class JobController {    private final static Logger LOGGER = LoggerFactory.getLogger(JobController.class);    @Autowired    private Scheduler scheduler;    @Autowired    private IQrtzJobDetailsService jobService;    @SuppressWarnings({ "unchecked", "rawtypes" })    @ApiOperation(value="新建任务")    @PostMapping("/add")    public R save(QuartzEntity quartz){        LOGGER.info("新增任务");        try {            //获取Scheduler实例、废弃、使用自动注入的scheduler、否则spring的service将无法注入            //Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();            //如果是修改  展示旧的 任务            if(quartz.getOldJobGroup()!=null){                JobKey key = new JobKey(quartz.getOldJobName(),quartz.getOldJobGroup());                scheduler.deleteJob(key);            }            Class cls = Class.forName(quartz.getJobClassName()) ;            cls.newInstance();            //构建job信息            JobDetail job = JobBuilder.newJob(cls).withIdentity(quartz.getJobName(),                    quartz.getJobGroup())                    .withDescription(quartz.getDescription()).build();            // 触发时间点            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression());            Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger"+quartz.getJobName(), quartz.getJobGroup())                    .startNow().withSchedule(cronScheduleBuilder).build();              //交由Scheduler安排触发            scheduler.scheduleJob(job, trigger);        } catch (Exception e) {            LOGGER.error("",e);            return R.error();        }        return R.ok();    }    @ApiOperation(value="任务列表")    @PostMapping("/list")    public R list(QuartzEntity quartz,Integer pageNo,Integer pageSize){        LOGGER.info("任务列表");        List<QuartzEntity> list = jobService.listQuartzEntity();        return R.ok(list);    }    @ApiOperation(value="触发任务")    @PostMapping("/trigger")    public  R trigger(QuartzEntity quartz, HttpServletResponse response) {        try {             JobKey key = new JobKey(quartz.getJobName(),quartz.getJobGroup());             scheduler.triggerJob(key);        } catch (SchedulerException e) {             e.printStackTrace();             return R.error();        }        return R.ok();    }    @PostMapping("/pause")    public  R pause(QuartzEntity quartz, HttpServletResponse response) {        LOGGER.info("停止任务");        try {             JobKey key = new JobKey(quartz.getJobName(),quartz.getJobGroup());             scheduler.pauseJob(key);        } catch (SchedulerException e) {             e.printStackTrace();             return R.error();        }        return R.ok();    }    @PostMapping("/resume")    public  R resume(QuartzEntity quartz, HttpServletResponse response) {        LOGGER.info("恢复任务");        try {             JobKey key = new JobKey(quartz.getJobName(),quartz.getJobGroup());             scheduler.resumeJob(key);        } catch (SchedulerException e) {             e.printStackTrace();             return R.error();        }        return R.ok();    }    @ApiOperation(value="移除任务")    @PostMapping("/remove")    public  R remove(QuartzEntity quartz, HttpServletResponse response) {        try {              TriggerKey triggerKey = TriggerKey.triggerKey(quartz.getJobName(), quartz.getJobGroup());            // 停止触发器            scheduler.pauseTrigger(triggerKey);              // 移除触发器            scheduler.unscheduleJob(triggerKey);              // 删除任务            scheduler.deleteJob(JobKey.jobKey(quartz.getJobName(), quartz.getJobGroup()));            System.out.println("removeJob:"+ JobKey.jobKey(quartz.getJobName()));        } catch (Exception e) {              e.printStackTrace();            return R.error();        }          return R.ok();    }}

可以通过controller提供的接口进行任务的动态添加和删除,也可以和TaskRunner那样硬编码加载任务。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开发架构二三事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 几种任务调度
  • quartz
    • springboot 1.0时代
      • 引入依赖
      • 配置
    • springboot 2.0时代
      • 引入依赖
    • 实战
      • 表说明
      • springboot 配置说明
      • 执行定时任务
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档