Springboot 集成Quartz,支持持久化,支持动态启停定时任务

Springboot 整合 Quartz(定时任务框架) Quartz是 OpenSymphony 开源组织在 Job scheduling 领域又一个开源项目,完全由 Java 开发,可以用来执行定时任务,类似于 java.util.Timer。持久性作业 - 就是保持调度定时的状态;作业管理 - 对调度作业进行有效的管理; 阅读详情

一.Quartz基本流程

  1. 首先需要创建任务(Job),比如定时发送短信邮件之类的,这是任务主体,也就是写业务逻辑的地方。

  2. 创建任务调度器(Scheduler),调用任务的主要API,主要用于启动、停止、暂停、恢复等操作。

  3. 创建任务明细(JobDetail),最开始编写好任务(Job)后,只是写好业务代码,并没有触发,这里需要用JobDetail来和之前创建的任务(Job)关联起来,便于执行。

  4. 创建触发器(Trigger),触发器是来定义任务的规则的,比如几点执行,几点结束,几分钟执行一次等等。这里触发器主要有两大类(SimpleTrigger和CronTrigger)。

  5. 根据Scheduler来启动JobDetail与Trigger

二、Springboot集成Quartz

1.Springboot引入依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

2.数据库中创建Quart相关的11张表

SQL脚本位置:org.quartz.impl.jdbcjobstore.oracle.tables_*.sql

以Mysql为例:

#
# Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
#
# PLEASE consider using mysql with innodb tables to avoid locking issues
#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#

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)
);

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)
);

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)
);

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(200) 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)
);

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)
);

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),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

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)
);

CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_GROUP  VARCHAR(200) NOT NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);

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)
);

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)
);

CREATE TABLE QRTZ_LOCKS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    LOCK_NAME  VARCHAR(40) NOT NULL,
    PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);


commit;

3.quartz.properties配置文件

  支持持久化。持久化的好处:支持集群,因为所有的任务信息都会保存到数据库中,可以控制事物,还有就是如果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务。

#使用自己的配置文件
org.quartz.jobStore.useProperties:true

#默认或是自己改名字都行
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
#如果使用集群,instanceId必须唯一,设置成AUTO
org.quartz.scheduler.instanceId = AUTO


org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true


#存储方式使用JobStoreTX,也就是数据库
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#是否使用集群(如果项目只部署到 一台服务器,就不用了)
org.quartz.jobStore.isClustered = false
org.quartz.jobStore.clusterCheckinInterval=20000
org.quartz.jobStore.tablePrefix = qrtz_
org.quartz.jobStore.dataSource = myDS

#配置数据源
#数据库中quartz表的表名前缀
org.quartz.dataSource.myDS.connectionProvider.class =com.springcloud.serviceconsumer.config.DruidQuartzProvider
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/test?serverTimezone=UTC&characterEncoding=utf8
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password = root
org.quartz.dataSource.myDS.maxConnection = 5

4.切换数据源

默认Quartz使用C3P0数据源,如何切换Druid数据源。

4.1 自定义类实现ConnectionProvider接口,属性与quartz.properties中的数据源相对应

package com.springcloud.serviceconsumer.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.quartz.SchedulerException;
import org.quartz.utils.ConnectionProvider;

import java.sql.Connection;
import java.sql.SQLException;

public class DruidQuartzProvider implements ConnectionProvider {
    /*
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *
     * 常量配置,与quartz.properties文件的key保持一致(去掉前缀),同时提供set方法,Quartz框架自动注入值。
     *
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */

    //JDBC驱动
    public String driver;
    //JDBC连接串
    public String URL;
    //数据库用户名
    public String user;
    //数据库用户密码
    public String password;
    //数据库最大连接数
    public int maxConnection;
    //数据库SQL查询每次连接返回执行到连接池,以确保它仍然是有效的。
    public String validationQuery;

    private boolean validateOnCheckout;

    private int idleConnectionValidationSeconds;

    public String maxCachedStatementsPerConnection;

    private String discardIdleConnectionsSeconds;

    public static final int DEFAULT_DB_MAX_CONNECTIONS = 10;

    public static final int DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION = 120;

    //Druid连接池
    private DruidDataSource datasource;

    /*
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *
     * 接口实现
     *
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    public Connection getConnection() throws SQLException {
        return datasource.getConnection();
    }

    public void shutdown() throws SQLException {
        datasource.close();
    }
    public void initialize() throws SQLException{
        if (this.URL == null) {
            throw new SQLException("DBPool could not be created: DB URL cannot be null");
        }

        if (this.driver == null) {
            throw new SQLException("DBPool driver could not be created: DB driver class name cannot be null!");
        }

        if (this.maxConnection < 0) {
            throw new SQLException("DBPool maxConnectins could not be created: Max connections must be greater than zero!");
        }

        datasource = new DruidDataSource();
        try{
            datasource.setDriverClassName(this.driver);
        } catch (Exception e) {
            try {
                throw new SchedulerException("Problem setting driver class name on datasource: " + e.getMessage(), e);
            } catch (SchedulerException e1) {
            }
        }

        datasource.setUrl(this.URL);
        datasource.setUsername(this.user);
        datasource.setPassword(this.password);
        datasource.setMaxActive(this.maxConnection);
        datasource.setMinIdle(1);
        datasource.setMaxWait(0);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(DEFAULT_DB_MAX_CONNECTIONS);

        if (this.validationQuery != null) {
            datasource.setValidationQuery(this.validationQuery);
            if(!this.validateOnCheckout)
                datasource.setTestOnReturn(true);
            else
                datasource.setTestOnBorrow(true);
            datasource.setValidationQueryTimeout(this.idleConnectionValidationSeconds);
        }
    }

    /*
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *
     * 提供get set方法
     *
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getURL() {
        return URL;
    }

    public void setURL(String URL) {
        this.URL = URL;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getMaxConnection() {
        return maxConnection;
    }

    public void setMaxConnection(int maxConnection) {
        this.maxConnection = maxConnection;
    }

    public String getValidationQuery() {
        return validationQuery;
    }

    public void setValidationQuery(String validationQuery) {
        this.validationQuery = validationQuery;
    }

    public boolean isValidateOnCheckout() {
        return validateOnCheckout;
    }

    public void setValidateOnCheckout(boolean validateOnCheckout) {
        this.validateOnCheckout = validateOnCheckout;
    }

    public int getIdleConnectionValidationSeconds() {
        return idleConnectionValidationSeconds;
    }

    public void setIdleConnectionValidationSeconds(int idleConnectionValidationSeconds) {
        this.idleConnectionValidationSeconds = idleConnectionValidationSeconds;
    }

    public DruidDataSource getDatasource() {
        return datasource;
    }

    public void setDatasource(DruidDataSource datasource) {
        this.datasource = datasource;
    }

    public String getDiscardIdleConnectionsSeconds() {
        return discardIdleConnectionsSeconds;
    }

    public void setDiscardIdleConnectionsSeconds(String discardIdleConnectionsSeconds) {
        this.discardIdleConnectionsSeconds = discardIdleConnectionsSeconds;
    }
}

4.2 指定quartz.properties数据源

org.quartz.dataSource.myDS.connectionProvider.class =com.springcloud.serviceconsumer.config.DruidQuartzProvider

5.创建任务Job

  需要实现Job接口,实现execute()方法,在execute()方法中写业务逻辑

//Job中的任务有可能并发执行,例如任务的执行时间过长,而每次触发的时间间隔太短,则会导致任务会被并发执行。如果是并发执行,就需要一个数据库锁去避免一个数据被多次处理。
@DisallowConcurrentExecution
public class MyTask implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        System.out.println("定时任务开始执行");
    }
}

6.创建任务调度器(Scheduler)

  StdSchedulerFactory factory = new StdSchedulerFactory("quartz.properties");
            scheduler = factory.getScheduler();

7.创建任务明细(JobDetail)

 JobDetail jobDetail = JobBuilder.newJob(className)
                .usingJobData("name","yu")
                .withIdentity(taskName,groupName)
                .build();

8.创建触发器

 CronTrigger trigger = TriggerBuilder.newTrigger()
                /**给当前JobDetail添加参数,K V形式,链式调用,可以传入多个参数,在Job实现类中,可以通过jobExecutionContext.getTrigger().getJobDataMap().get("orderNo")获取值*/
                .usingJobData("orderNo", "123456")
                /**添加认证信息,有3种重写的方法,我这里是其中一种,可以查看源码看其余2种*/
                .withIdentity(taskName,groupName)
                /**开始执行时间*/
                .startNow()
                /**添加执行规则,SimpleTrigger、CronTrigger的区别主要就在这里,我这里是demo,写了个每5秒钟执行一次*/
                .withSchedule(CronScheduleBuilder.cronSchedule("*/5 * * * * ?"))
                .build();//执行

9.添加并且启动任务

 JobKey jobKey = JobKey.jobKey(taskName, groupName);
            boolean isExist = scheduler.checkExists(jobKey);
            if (!isExist) {
                scheduler.scheduleJob(jobDetail,trigger);
            }
            if (!scheduler.isStarted()) {
                scheduler.start();
            }

10.附:quartz工具类

package com.springcloud.serviceconsumer.utils;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

public class TaskSchedulingService {

    public static Logger logger = LoggerFactory.getLogger(TaskSchedulingService.class);

    private static TaskSchedulingService taskSchedulingService = null;
    private Scheduler scheduler = null;

    public TaskSchedulingService() {
        createScheduler();
    }


    private void createScheduler() {
        try {
            StdSchedulerFactory factory = new StdSchedulerFactory("quartz.properties");
            scheduler = factory.getScheduler();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * 单例获取任务调度器
     */
    public static synchronized TaskSchedulingService getInstance() {
        if (taskSchedulingService == null || taskSchedulingService.scheduler == null) {
            return new TaskSchedulingService();
        }
        return taskSchedulingService;
    }

    /**
     * 添加定时任务
     * @param taskName
     * @param groupName
     * @param className
     */
    public void addTask(String taskName, String groupName,Class className) {
        JobDetail jobDetail = JobBuilder.newJob(className)
                .usingJobData("name","yu")
                .withIdentity(taskName,groupName)
                .build();
        CronTrigger trigger = TriggerBuilder.newTrigger()
                /**给当前JobDetail添加参数,K V形式,链式调用,可以传入多个参数,在Job实现类中,可以通过jobExecutionContext.getTrigger().getJobDataMap().get("orderNo")获取值*/
                .usingJobData("orderNo", "123456")
                /**添加认证信息,有3种重写的方法,我这里是其中一种,可以查看源码看其余2种*/
                .withIdentity(taskName,groupName)
                /**开始执行时间*/
                .startNow()
                /**添加执行规则,SimpleTrigger、CronTrigger的区别主要就在这里,我这里是demo,写了个每5秒钟执行一次*/
                .withSchedule(CronScheduleBuilder.cronSchedule("*/5 * * * * ?"))
                .build();//执行

        try {
            JobKey jobKey = JobKey.jobKey(taskName, groupName);
            boolean isExist = scheduler.checkExists(jobKey);
            if (!isExist) {
                scheduler.scheduleJob(jobDetail,trigger);
            }
            if (!scheduler.isStarted()) {
                scheduler.start();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 暂停定时任务
     * @param taskName
     * @param groupName
     */
    public void pauseTask(String taskName, String groupName) {
//        JobKey jobKey = JobKey.jobKey(taskName, groupName);
        TriggerKey triggerKey = TriggerKey.triggerKey(taskName,groupName);
        boolean isExist = false;
        try {
            isExist = scheduler.checkExists(triggerKey);
            if (isExist) {
                scheduler.pauseTrigger(triggerKey);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 恢复定时任务
     * @param taskName
     * @param groupName
     */
    public void resumeTask(String taskName, String groupName) {
//        JobKey jobKey = JobKey.jobKey(taskName, groupName);
        TriggerKey triggerKey = TriggerKey.triggerKey(taskName,groupName);
        boolean isExist = false;
        try {
            isExist = scheduler.checkExists(triggerKey);
            if (isExist) {
                scheduler.resumeTrigger(triggerKey);
                if (!scheduler.isStarted()) {
                    scheduler.start();
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除定时任务
     * @param taskName
     * @param groupName
     */
    public void deleteTask(String taskName, String groupName) {
        JobKey jobKey = JobKey.jobKey(taskName, groupName);
        boolean isExist = false;
        try {
            isExist = scheduler.checkExists(jobKey);
            if (isExist) {
                scheduler.deleteJob(jobKey);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取所有定时任务
     * @param jobGrop
     */
    public void getAllTask(String jobGrop) {
        try {
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            if (null != jobKeys && !jobKeys.isEmpty()) {
                Iterator<JobKey> it = jobKeys.iterator();
                while (it.hasNext()) {
                    JobKey jobKey = it.next();
                    String jobName = jobKey.getName();
                    String jobGroup = jobKey.getGroup();
                    if (jobGroup != null && jobGroup.equals(jobGrop)) {
                        if (jobName != null && !jobName.equals("")) {
                        }
                    }
                }
            }
        } catch (SchedulerException e) {
            logger.error(e.getMessage(), e);
        }
    }

}

 

SpringBoot整合Quartz 目录`Quartz` 简介 Quartz 简介 Quartz 是一款功能强大的开源任务调度框架,几乎可以集成到任何 Java 应用程序中(小到单机应用,大到分布式应用)。Quartz 可用于创建简单或复杂的任务调度,用以执行数以万计的任务。任务被定义为标准化的 Java 组件,Java 编写的任务都可以被执行 Quartz 是一个任务日程管理系统,一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统 Quartz 用一个小 Java 库发布文件(.jar文件),这个库文件包含了所 阅读详情

相关推荐

SpringBoot 整合 Quartz 定时任务框架

Quartz 其实就是通过一个调度线程不断的扫描数据库中的数据来获取到那些已经到点要触发的任务,然后调度执行它的。表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。在此基础上,我们再额外增加一张表,与我们可能有业务关联的信息整合,这啥啥允许为空,是方便我写测试~,并非正例。启动项目,让我们拿起来postman来测试吧,康康该如何使用,数据表在使用的时候,又有怎么样的变化~表示一个工作,要执行的具体内容。...

m0_73256420的博客 737

Spring Boot 集成 Quartz(任务调度框架)

Quartz 是完全由Java开发的作业调度框架,当定时任务愈加复杂时,使用Spring注解@Schedule已经不能满足业务需要。} }return JobBuilder . newJob(SampleJob . class) . withIdentity("job" , "group") . withDescription("任务描述:内存方式运行") . storeDurably() . build();} }

欲变世界,先变其身 6257

quartz 持久化集成springBoot Demo

本文介绍了Quartz持久化与SpringBoot集成的优势及MySQL表初始化方法。Quartz持久化可实现任务零丢失、集群高可用、动态运维、与Spring生态无缝整合等企业级需求,支持幂等、事务、审计等功能。MySQL表初始化部分详细说明了11个核心表的作用及关系,包括任务定义(QRTZ_JOB_DETAILS)、触发器(QRTZ_TRIGGERS)等,并提供了完整的建表SQL脚本。该方案能确保任务调度在应用重启、集群部署等场景下的可靠性,是构建健壮定时任务系统的理想选择。

杨杨杨~~的博客 2084

springboot整合quartz

springboot集成调度框架quartz,各类定时框架比较

太上码农 1万+

【QUARTZ】springboot+quartz动态配置定时任务

​ Quartz 定时任务可分为Trigger(触发器)、Job(任务)和Scheduler(调度器),定时任务的逻辑大体为:创建触发器和任务,并将其加入到调度器 ​

niuchenliang524的博客 2802

SpringBoot快速整合Quartz动态管理定时任务

SpringBoot快速整合Quartz动态管理定时任务 背景 ​ 如题,上个版本产品提出了一个报告需求的整体大功能,其中有一个小的子功能就是开发一个在页面==动态添加、删除、修改、启停==的定时任务来执行一系列的操作(生成周期报告、发送邮件等);关于SpringBoot中的定时任务,大家应该都比较熟悉,在主启动类上添加***@EnableScheduling***,然后直接在需要定时执行的方法上直接添加***@Scheduled(cron = “”)并且添加上定时任务的cron表达式即可;但是这种方式有一

weixin_43715518的博客 3786

SpringBoot定时任务动态管理,Quartz集成

在SpringBoot项目中实现定时任务动态管理是一个常见的需求,业务场景中经常需要根据运行情况调整定时任务的执行时间或启停状态。本文将详细介绍如何在SpringBoot中集成Quartz框架来实现动态定时任务的管理。1. **任务持久化**:建议将任务信息持久化到数据库,保证应用重启后任务不丢失。2. **任务幂等**:保证任务重复执行不会产生副作用。3. **监控报警**:增加任务执行监控和失败报警机制。4. **任务分组**:合理规划任务分组,方便管理。return "添加任务成功";

2509_93945572的博客 427

麒麟v10(ky10.x86_64)升级——openssl-3.2.2、openssh-9.8p1

执行命令: make -j 4 && make install 这里要等待一段时间,等待编译完成。执行命令: ./configure --prefix=/usr/local/src/zlilb。执行命令: ./config --prefix=/usr/local/src/openssl。执行命令: make -j 4 && make test && make install。执行命令: make -j 4 && make install。执行命令: /etc/init.d/sshd restart。

X_yufei的博客 7429

Spring boot整合quartz方法

然后,定时任务继承TaskJob,并实现其方法。

2509_94461900的博客 444

解决vLLM安装卡在vllm-nccl-cu12依赖项的实战指南

本文提供了解决vLLM安装过程中卡在vllm-nccl-cu12依赖项的详细指南。通过分析CUDA版本兼容性问题,介绍了三种实用解决方案:安装指定版本vLLM、手动安装nccl-cu12依赖以及升级CUDA到12.x版本,并特别针对离线环境提供了安装建议,帮助开发者顺利完成vLLM的安装部署。

weixin_29098367的博客 516

S/4中的16种特殊库存类型

S/4中的16种特殊库存类型

yanzibing99的博客 1万+

重学SpringBoot3-整合Quartz定时任务

Quartz 是一个开源的任务调度框架,用于在应用程序中创建、管理和调度定时任务。将 Quartz 和 Spring Boot 3 结合,可以轻松实现定时任务的灵活管理。本文将详细介绍如何在 Spring Boot 3 项目中集成 Quartz Scheduler 并实现示例任务的调度。

CoderJia的学习之路 5519

资金穿透分析

我们把准备好的银行数据导入到软件中,导入具体步骤这里不做详解,大家可以通过“清林情报分析师”公众号,查看操作视频第二节

清林情报分析师 3493

深入Quartz,优雅地管理你的定时任务

Quartz是Java定时任务领域一个非常优秀的框架,本文从Quartz的设计简析到Quartz的基本使用,带你快速地理解Quartz

云深不知处 6341

spm FMRI 各种小问题合集

预处理 1、预处理结果从normalize之后开始头歪、变形 问题描述:如下图 原因:DICOM2NIfTI时必须检查对应的T1像。下面是两种错误形式,第一种容易发现,第二种容易忽视,大脑失状位左右颠倒。 解决:重新转了一回格式,建议用SPM fmri进行格式转换。之前是用MRIconvert转换的,用了两台电脑,有的T1结果是对的,不确定什么原因产生的错位,操作都是一样的。 2、Check reg大脑图片边缘出边框 问题描述: 原因:应该是图片排版导致的,单独check就会发现大脑是全的。 解决

weixin_44669441的博客 1677

京东技术产品经理面试全记录:从简历投递到一面45分钟实战复盘

本文深度复盘京东技术产品经理面试全流程,从策略准备、思维题拆解、项目阐述到反问谈判,提供了一套可演练的求职策略体系。文章强调该岗位需具备横跨技术与商业的枢纽能力,并通过“QQ分组vs微信标签”等案例,剖析了产品思维与结构化表达在面试中的关键作用,助力候选人将紧张转化为掌控感。

weixin_29275257的博客 630

SpringBoot集成Quartz实现动态定时任务

一、Quartz 简介 Quartz 是 OpenSymphony 开源组织在 Job Scheduling 领域又一个开源项目,是完全由 Java 开发的一个开源任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。 Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中,它提供了巨大的灵活性而不牺牲简单性 当定时任务愈加复杂时,使用 Spring 注解 @Schedule 已经不能满

微微~ 2397

OpenMM | PDBFixer 用于蛋白质预处理

PDBFixer 用于蛋白质预处理

DrugOne 3007

SpringBoot整合Quartz实现动态定时任务

Spring Boot整合Quartz实现动态定时任务 简介: 虽然Spring Boot融合了基于注解的定时任务,但是任务的定时器需在代码中配置,代码入侵较强,例如:若需改动某一定时任务的执行周期,则需改动代码再发版,且无法实现具体任务的暂停与启动。 Quartz可实现定时任务配置的持久化,将相关定时任务信息(对应任务类名、任务当前状态、cron表达式)持久化到数据库,从而在页面实现对具体任务的暂停、启动、执行周期的修改等操作而不需要改动代码。 环境: Java 8、Spring Boot 1.5.13、

whothinkyouare的博客 962

YOLOv11改进 | 注意力篇 | YOLOv11引入CBAM注意力机制

我们的实验表明各种模型的分类和检测性能得到了一致的改进,证明了 CBAM 的广泛适用性。简单介绍:CBAM的主要思想是通过关注重要的特征并抑制不必要的特征来增强网络的表示能力。模块首先应用通道注意力,关注"重要的"特征,然后应用空间注意力,关注这些特征的"重要位置"。到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv11改进有效涨点专栏,本专栏目前为新开的,后期我会根据各种前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

tsg6698的博客 2万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

《SpringBoot中@Scheduled和Quartz的区别是什么?分布式定时任务框架选型实战》​

Scheduled是轻量级单机定时任务的便捷选择,而Quartz等框架则为企业级调度需求提供了完整的解决方案。在实际项目中,需根据任务复杂度、集群部署需求、运维成本等因素综合决策。对于Spring Boot应用,若后续可能演进为分布式架构,初期可优先考虑使用XXL-JOB或Elastic Job等云原生友好的调度中间件。

摘星编程的博客 1万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Springboot整合Quartz实现动态定时任务

简介 Quartz是一款功能强大的任务调度器,可以实现较为复杂的调度功能,如每月一号执行、每天凌晨执行、每周五执行等等,还支持分布式调度。本文使用Springboot+Mybatis+Quartz实现对定时任务的增、删、改、查、启用、停用等功能。并把定时任务持久化到数据库以及支持集群。对于如何创建Springboot项目和与Mybatis整合可以参考上篇文章:[spring-boot整合M...

lisheng19870305的专栏 537

SpringBoot 整合 Quartz 动态定时任务

简介 Quartz是一款功能强大的任务调度器,可以实现较为复杂的调度功能,如每月一号执行、每天凌晨执行、每周五执行等等,还支持分布式调度。本文使用Springboot+Mybatis-plus+Quartz实现对定时任务的增、删、改、查、启用、停用等功能。并把定时任务持久化到数据库,并且还实现动态编译运行Java,动态执行字符串代码模板。 为什么要使用Quartz 多任务情况下,quartz...

shareloke 735

玩转 Spring Boot 集成篇(定时任务框架Quartz)

在日常项目研发中,定时任务可谓是必不可少的一环,关于 Spring Boot 如何实现静态定时任务、动态定时任务以及如何开启多线程跑任务,均已在上篇分享过,不再赘述。虽然 Spring B...

一猿小讲 7142
上一篇: Linux利用Docker安装RabbitMq!
ys_code
博客等级 码龄10年 13粉丝 24原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值