springboot整合quartz(集群环境)

2023-05-16

    使用quartz实现定时任务,若是部署多台机器,那么到了时间点,多台服务器便会同时均开始执行定时任务,这不符合我们的功能实现。
    quartz集群分为水平集群和垂直集群,水平集群即将定时任务节点部署在不同的服务器,其最大的问题就是时钟同步问题,若时钟不能同步,则会导致集群中各个节点状态紊乱,造成不可预知的后果;垂直集群则是集群各节点部署在同一台服务器,时钟同步自然不是问题,但存在单点故障问题,服务器宕机会严重影响服务的可用性。因此,要结合实际情况来考虑集群方案。
    quartz集群的实现方式在于11张表,集群节点相互之间不通信,而是通过定时任务持久化加锁的方式来实现集群。

1、首先下载quartz集群需要创建的表,下载地址如下:

http://www.quartz-scheduler.org/downloads/
这里写图片描述

2、下载之后解压,进入如下目录,创建数据库表
quartz-2.2.3-distribution\quartz-2.2.3\docs\dbTables


这里写图片描述
注:若是mysql数据库,则使用上图的sql文件。


11张表功能说明:

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

mysql中数据库表创建语句如下:

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; 

3、创建springboot项目

①pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

	<groupId>com.button</groupId>
	<artifactId>springboot-quartz</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>quartz-springboot</name>
	<description>springboot集成quartz(集群)</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.5.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<!--mysql链接依赖 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.apache.tomcat</groupId>
					<artifactId>tomcat-jdbc</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>com.zaxxer</groupId>
			<artifactId>HikariCP-java7</artifactId>
			<version>2.4.13</version>
		</dependency>
		<!--quartz依赖 -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
		</dependency>
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz-jobs</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
			<scope>true</scope>
		</dependency>
		<!-- test -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
					<fork>true</fork>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

注:quartz的核心包如下

<dependency> 
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
</dependency>

②quartz.properties

#quartz集群配置  
#调度标识名 集群中每一个实例都必须使用相同的名称    
org.quartz.scheduler.instanceName=DefaultQuartzScheduler
#ID设置为自动获取 每一个必须不同  
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.makeSchedulerThreadDaemon=true
#线程池的实现类(一般使用SimpleThreadPool即可满足需求)  
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
#指定在线程池里面创建的线程是否是守护线程
org.quartz.threadPool.makeThreadsDaemons=true
#指定线程数,至少为1(无默认值)
org.quartz.threadPool.threadCount:20
#设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5) 
org.quartz.threadPool.threadPriority:5
#数据保存方式为数据库持久化  
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
#数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库  
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#表的前缀,默认QRTZ_  
org.quartz.jobStore.tablePrefix=QRTZ_
#是否加入集群
org.quartz.jobStore.isClustered=true
# 信息保存时间 默认值60秒   
org.quartz.jobStore.misfireThreshold=25000

更多详细配置可参考如下:
https://blog.csdn.net/huang1060/article/details/68062496

③核心配置类
QuartzConfigure.java

package com.button.timer.conf;

import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.quartz.spi.JobFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.button.timer.job.ButtonTimerJob;

@Configuration
public class QuartzConfigure {
	// 配置文件路径
	private static final String QUARTZ_CONFIG = "/quartz.properties";
	
	@Autowired
    @Qualifier(value = "dataSource")
    private DataSource dataSource;
	
	@Value("${quartz.cronExpression}")
	private String cronExpression;

	/**
	 * 从quartz.properties文件中读取Quartz配置属性
	 * @return
	 * @throws IOException
	 */
    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource(QUARTZ_CONFIG));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }
    
    /**
     * JobFactory与schedulerFactoryBean中的JobFactory相互依赖,注意bean的名称
     * 在这里为JobFactory注入了Spring上下文
     * 
     * @param applicationContext
     * @return
     */
    @Bean
    public JobFactory buttonJobFactory(ApplicationContext applicationContext) {
    	AutoWiredSpringBeanToJobFactory jobFactory = new AutoWiredSpringBeanToJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        return jobFactory;
    }

    /**
     * 
     * @param buttonJobFactory  为SchedulerFactory配置JobFactory
     * @param cronJobTrigger  
     * @return
     * @throws IOException
     */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(JobFactory buttonJobFactory, Trigger... cronJobTrigger) throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setJobFactory(buttonJobFactory);
        factory.setOverwriteExistingJobs(true);
        factory.setAutoStartup(true); // 设置自行启动
        factory.setQuartzProperties(quartzProperties());
        factory.setTriggers(cronJobTrigger);
        factory.setDataSource(dataSource);// 使用应用的dataSource替换quartz的dataSource
        return factory;
    }

    /**
     * 配置JobDetailFactory
     * JobDetailFactoryBean与CronTriggerFactoryBean相互依赖,注意bean的名称
     * 
     * @return
     */
    @Bean
    public JobDetailFactoryBean buttonobDetail() {
         //集群模式下必须使用JobDetailFactoryBean,MethodInvokingJobDetailFactoryBean 类中的 methodInvoking 方法,是不支持序列化的
         JobDetailFactoryBean jobDetail = new JobDetailFactoryBean();
         jobDetail.setDurability(true); 
         jobDetail.setRequestsRecovery(true);
         jobDetail.setJobClass(ButtonTimerJob.class); 
         return jobDetail; 
    }
    
    /**
     * 配置具体执行规则
     * @param buttonobDetail
     * @return
     */
    @Bean
    public CronTriggerFactoryBean cronJobTrigger(JobDetail buttonobDetail) {
        CronTriggerFactoryBean tigger = new CronTriggerFactoryBean();
        tigger.setJobDetail(buttonobDetail);
        tigger.setStartDelay(2000);   //延迟启动
        tigger.setCronExpression(cronExpression);  //从application.yml文件读取
        return tigger;
    }
}

AutoWiredSpringBeanToJobFactory.java

package com.button.timer.conf;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
/**
 * 
 * @author Button
 * 为JobFactory注入SpringBean,否则Job无法使用Spring创建的bean
 */
public class AutoWiredSpringBeanToJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
	private transient AutowireCapableBeanFactory beanFactory;

    @Override
    public void setApplicationContext(final ApplicationContext context) {
        beanFactory = context.getAutowireCapableBeanFactory();
    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        beanFactory.autowireBean(job);
        return job;
    }
}

④定时任务类

ButtonTimerJob.java

package com.button.timer.job;

import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @DisallowConcurrentExecution : 此标记用在实现Job的类上面,意思是不允许并发执行.
 * 注org.quartz.threadPool.threadCount的数量有多个的情况,@DisallowConcurrentExecution才生效
 */
@DisallowConcurrentExecution
public class ButtonTimerJob implements Job{
    private static final Logger logger = LoggerFactory.getLogger(ButtonTimerJob.class);

    /**
     * 核心方法,Quartz Job真正的执行逻辑.
     * @param JobExecutionContext中封装有Quartz运行所需要的所有信息
     * @throws JobExecutionException execute()方法只允许抛出JobExecutionException异常
     */
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		logger.info("--------------定时任务执行逻辑---------------------");
	}
}

⑤springboot项目入口

QuartzSpringbootApplication.java

package com.button.timer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class QuartzSpringbootApplication {

	public static void main(String[] args) {
		SpringApplication.run(QuartzSpringbootApplication.class, args);
	}
}

⑥项目配置文件

application.yml

server:
  port: 8080

logging: 
    file: logback.xml
    
spring: 
    dataSource: 
        url: jdbc:mysql://***********:3306/button-pro?characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true&useSSL=true&zeroDateTimeBehavior=convertToNull
        username: root
        password: ******
        driver-class-name: com.mysql.jdbc.Driver
        type: com.zaxxer.hikari.HikariDataSource
        hikari:
            minimum-idle: 5
            maximum-pool-size: 15
            idle-timeout: 30000
            pool-name: DatebookHikariCP
            max-lifetime: 1800000
            connection-timeout: 30000
            connection-test-query: 'SELECT 1'
            
quartz:
    cronExpression: 0/5 * 8-20 * * ?

⑦日志配置文件

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
    <property name="LOG_HOME" value="/data/button/springboot" />

	<!-- 控制台输出 -->
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
			<!--格式化输出,%d:日期;%thread:线程名;%-5level:级别,从左显示5个字符宽度;%msg:日志消息;%n:换行符 -->
			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n</pattern>
		</encoder>
	</appender>
	<!-- 按照每天生成日志文件 -->
	<appender name="FILE"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<file>${LOG_HOME}/springboot_button.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<!--日志文件输出的文件名 -->
			<FileNamePattern>
				${LOG_HOME}/springboot_button.log.%d{yyyy-MM-dd}.%i.log
			</FileNamePattern>
			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 日志文件最大size -->
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
		</rollingPolicy>
		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
			<!--格式化输出,%d:日期;%thread:线程名;%-5level:级别,从左显示5个字符宽度;%msg:日志消息;%n:换行符 -->
			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n</pattern>
		</encoder>
	</appender>

	<!-- 日志输出级别 -->
	<root level="DEBUG">
		<appender-ref ref="STDOUT" />
		<appender-ref ref="FILE" />
	</root>
</configuration>

代码如下:
https://gitee.com/superbutton/SpringBoot-Components/tree/develop/Springboot-Quartz-Cluster

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springboot整合quartz(集群环境) 的相关文章

随机推荐

  • 【智能家居】Home Assistant入门安装并内网穿透实现远程安全控制

    文章目录 前言1 安装Home Assistant2 配置Home Assistant3 安装cpolar内网穿透3 1 windows系统3 2 Linux系统3 3 macOS系统 4 映射Home Assistant端口5 公网访问H
  • Windows搭建Maven环境并在Eclipse中进行配置

    Maven环境 下载maven并配置 http maven apache org download cgi 下载完成如下 xff1a 接下来开始配置maven环境 xff1a 计算机 gt 右键 属性 gt 高级系统设置 gt 环境变量 g
  • 初见Ubuntu

    Ubuntu入门与常用娱乐软件安装 设置语言环境设置服务器镜像源安装搜狗输入法安装网易云音乐 一 设置语言环境 在系统右上角找到小齿轮图标 xff0c 点击选择 System Settings 选项 在打开的设置界面点击 Language
  • Ubuntu终端命令详述

    一 基本终端命令 1 调整终端窗口的字体大小 34 ctrl 43 shift 43 61 34 放大终端窗口的字体 34 ctrl 43 34 缩小终端窗口的字体 2 Linux命令的基本使用 序号命令对应英文作用01lslist查看当前
  • Ubuntu安装并连接Mysql

    安装配置MySql sudo apt install mysql server XX 提示 xff1a 当输入mysql时便可连续按 tab 键两次便可得到提示信息 xff0c 根据信息选择安装 安装过程中会提示输入mysql服务密码 xf
  • vi的使用与基本命令

    vi的使用 一 初识vi 1 什么是vi vi xff0c 即终端中一款编辑器 2 vi的应用场景 当我们要通过远程连接到服务器时 xff0c 此时没有图形界面 xff0c 当我们要对服务器上的文件进行编辑时 xff0c 便可以使用vi进行
  • Ubuntu下安装并配置Redmine

    Redmine安装与使用 Redmine是什么 xff1f Redmine是用Ruby开发的基于web的项目管理软件 xff0c 是用ROR框架开发的一套跨平台项目管理系统 xff0c 支持多种数据库 xff0c 多项独特功能 这种 Web
  • Ubuntu下安装ReviewBoard

    ReviewBoard安装与使用 ReviewBoard是什么 xff1f ReviewBoard是个开源的 可扩展的 友好的基于Web的代码评审工具 xff0c 是用Python框架Django开发的 ReviewBoard是通过Pyth
  • Ubuntu安装redis,Docker下安装redis以及redis基本配置说明

    一 什么是redis redis是一个key value存储系统 和Memcached类似 xff0c 它支持的数据类型相对更多 xff0c 包括string 字符串 list 链表 set 集合 zset sorted set 有序集合
  • Ubuntu安装memcache

    一 什么是memcache memcache是一个高性能的分布式的内存对象缓存系统 xff0c 通过在内存里维护一个统一的巨大的hash表 xff0c 它能够用来存储各种格式的数据 xff0c 包括图像 视频 文件以及数据库检索的结果等 简
  • Ubuntu安装Apache+Svn+Submin

    安装之前建议先更新 sudo apt update sudo apt upgrade 一 安装配置Apache 1 安装apache sudo apt install apache2 2 开启apache2模块 a2enmod rewrit
  • ROS坐标系统,常见的坐标系和其含义

    原链接 运行测试平台 小强ROS机器人 常见的坐标系 在使用ROS进行定位导航等操作时 xff0c 我们经常会遇到各种坐标系 每种坐标系都有明确的含义 理论上坐标系的名称可以是随意的 xff0c 但是为了方便不同的软件间共享坐标信息 xff
  • ReviewBoard+SVN配置强制code review

    本文需要在svn与reviewboard安装成功之后开始进行配置 xff0c 详情参考如下两篇文章根据实际情况操作 xff1a Ubuntu安装Apache 43 Svn 43 Submin https blog csdn net qq 2
  • Ubuntu安装配置Maven私服Nexus

    1 简介 Maven是什么 xff1f Maven是一个采用纯Java编写的开源项目管理工具 Maven采用了一种被称之为Project Object Model POM 的概念来管理项目 xff0c 所有的项目配置信息都被定义在一个叫做P
  • Ubuntu安装配置Docker

    一 Docker简介 Docker 是一个开源的应用容器引擎 xff0c 可以轻松的为任何应用创建一个轻量级的 可移植的 自给自足的容器 xff0c 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中 xff0c 然后发布到任何流行的
  • Ubuntu安装ftp实现文件上传

    ftp服务安装与配置 sudo apt install vsftpd 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img UlscHRVo 1598855886357 https img blog csdn net
  • Docker安装Tomcat镜像并部署web项目简述

    一 安装Tomcat 1 查找Docker Hub上的tomcat镜像 docker search tomcat 2 拉取官方的镜像 docker pull tomcat 等待下载完毕 xff0c 需要一些时间 3 查看docker所有的镜
  • Docker删除镜像和容器

    删除docker中的镜像 xff0c 我们可以使用如下命令 xff1a docker rmi 镜像id 删除docker中的容器可以使用如下命令 xff1a docker rm 容器id 使用如下命令可以查看当前正在运行的容器 docker
  • ubuntu安装SonarQube实现代码质量检测

    一 ubuntu中安装jdk 下载并安装jdk 详细过程可参考 xff1a https blog csdn net qq 26709459 article details 80466239 二 ubuntu中安装mysql 详细过程可参考
  • springboot整合quartz(集群环境)

    使用quartz实现定时任务 xff0c 若是部署多台机器 xff0c 那么到了时间点 xff0c 多台服务器便会同时均开始执行定时任务 xff0c 这不符合我们的功能实现 quartz集群分为水平集群和垂直集群 xff0c 水平集群即将定