Springboot+Quartz集群配置

看了一些网上的文章,都不太合我意,集众家之长,来个自己的版本。原理和介绍就不搬来搬去了,直接上代码吧。

目录

一.POM文件

二.application-quartz.properties

三.java文件

     3.1 Application

     3.2 QuartzSchedulerConfig配置一下,类名自己随便改

     3.3 StartApplicationListener应用启动时调用一下QuartzTasks添加定时任务

     3.4 QuartzTasks用来启动时添加或更新所有定时任务,类名自己随便改

     3.5 Job1用来实现具体的任务逻辑,类名自己随便改,每个任务创建一个类

     3.6 IXXXService的接口和Service实现类这里不做记载了,直接按自己的业务逻辑来

四.创建quartz的表


一.POM文件

        
        
            org.springframework.boot
            spring-boot-starter-quartz
        

     这里只记载了quartz的依赖,其他部分根据自己需要去弄吧。因为我的spring-boot-starter-parent采用的版本是2.3.3.RELEASE,所以对应的spring-boot-starter-quartz的版本也是2.3.3.RELEASE,quartz的版本是2.3.2

二.application-quartz.properties

################ quartz集群配置 
# 设置quartz任务的数据持久化方式,默认是内存方式,配置JDBC以使用数据库方式持久化任务
spring.quartz.job-store-type=jdbc
# 调度标识名 集群中每一个实例都必须使用相同的名称    
spring.quartz.properties.org.quartz.scheduler.instanceName=ComplianceAuditQuartzScheduler
# ID设置为自动获取 每一个必须不同  
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
spring.quartz.properties.org.quartz.scheduler.makeSchedulerThreadDaemon=true
# 线程池的实现类(一般使用SimpleThreadPool即可满足需求)  
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
# 指定在线程池里面创建的线程是否是守护线程
spring.quartz.properties.org.quartz.threadPool.makeThreadsDaemons=true
# 指定线程数,至少为1(无默认值)
spring.quartz.properties.org.quartz.threadPool.threadCount:10
# 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5) 
spring.quartz.properties.org.quartz.threadPool.threadPriority:5
# 自创建父线程
spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
# 数据保存方式为数据库持久化  
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
# 数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库  
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 表的前缀,默认QRTZ_  
spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_
# 是否加入集群
spring.quartz.properties.org.quartz.jobStore.isClustered=true
# 检入到数据库中的频率(单位毫秒)。clusterChedkinInterval越小,Scheduler节点检查失败的 Scheduler实例就越频繁。默认值是 15000(即15秒)。
spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=20000
# 设置调度引擎对触发器超时的忍耐时间 (单位毫秒)
spring.quartz.properties.org.quartz.jobStore.misfireThreshold=60000

     我这里是单独放了个配置文件,也可以直接写在application.properties里。单独配置文件的时候,别忘了在application.properties里的spring.profiles.active里添加一下引用。我这里的引用是:"spring.profiles.active=jdbc,reids,log,system,quartz" 。如果没有这个配置文件,quartz默认启动为单机版。

三.java文件

     3.1 Application

           在入口Application类上加上 @EnableScheduling的注解

     3.2 QuartzSchedulerConfig配置一下,类名自己随便改

package com.study.quartz.config;

import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

@Configuration
public class QuartzSchedulerConfig implements SchedulerFactoryBeanCustomizer {

	@Override
	public void customize(SchedulerFactoryBean schedulerFactoryBean) {
        // 延时10s启动定时任务,避免系统未完全启动却开始执行定时任务的情况
        schedulerFactoryBean.setStartupDelay(10);
        // 自动启动
        schedulerFactoryBean.setAutoStartup(true);
        // 覆盖已存在的任务,用于Quartz集群,QuartzScheduler启动会更新已存在的Job
        schedulerFactoryBean.setOverwriteExistingJobs(true);
    }
}

     3.3 StartApplicationListener应用启动时调用一下QuartzTasks添加定时任务

package com.study.quartz.config;

import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;

import com.study.quartz.task.QuartzTasks;

@Configuration
public class StartApplicationListener implements ApplicationListener {
    private static final Logger logger = LoggerFactory.getLogger(StartApplicationListener.class);

    @Autowired
    private QuartzTasks quartzTasks;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 防止重复执行
        if (event.getApplicationContext().getParent() == null) {
            // 添加quartz定时任务
            logger.info("开始-添加quartz定时任务");
            try {
                quartzTasks.addQuartzJobs();
            } catch (SchedulerException e) {
                logger.error("添加quartz定时任务失败", e);
            }
            logger.info("结束-添加quartz定时任务");

            // 删除旧的不要的quartz定时任务
            logger.info("开始-删除旧的不要的quartz定时任务");
            try {
                quartzTasks.deleteQuartzJobs();
            } catch (SchedulerException e) {
                logger.error("删除旧的不要的quartz定时任务失败", e);
            }
            logger.info("结束-删除旧的不要的quartz定时任务");
        }
    }
}

     3.4 QuartzTasks用来启动时添加或更新所有定时任务,类名自己随便改

           application-system.properties里配置一下任务定时的cron,我这里定义了"cronJob1=0 */2 * * * ?",每两分钟执行一次。

package com.study.quartz.task;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Component
@PropertySource("classpath:application-system.properties")
public class QuartzTasks {
    /**
     * 注入任务调度器
     */
    @Autowired
    private Scheduler scheduler;

    /**
     * 默认时区
     */
    private static final TimeZone defaultTimeZone = TimeZone.getTimeZone("Asia/Shanghai");
    /**
     * 任务分组
     */
    private static final String GROUP_A = "GroupA";

    @Value("${cronJob1}")
    private String cronJob1;
    /**
     * 添加定时任务
     *
     * @throws SchedulerException
     */
    public void addQuartzJobs() throws SchedulerException {
        // 添加定时任务:Job1
        addJob(scheduler, Job1.class, GROUP_A , "Job1", cronJob1);
        // 下面可以添加其他定时任务
        // 
    }
    
    /**
     * 删除旧的不要的定时任务
     *
     * @param scheduler Quartz调度器
     * @throws SchedulerException
     */
    public void deleteQuartzJobs() throws SchedulerException {
        // 删除旧的不要的定时任务
        // deleteJob(scheduler, groupName, jobName);
    }

    /**
     * 添加定时任务
     * 
     * @param scheduler Quartz调度器
     * @param jobClass 任务类
     * @param groupName 任务分组
     * @param jobName 任务名
     * @param jobCron 任务定时cron
     * @throws SchedulerException
     */
    private void addJob(Scheduler scheduler, Class jobClass, String groupName, String jobName,
            String jobCron) throws SchedulerException {
        JobDetail jobDetail = JobBuilder.newJob(jobClass)
                // 任务名称和任务分组 组合成任务唯一标识
                .withIdentity("Job" + jobName, "Job" + groupName)
                // 无触发器指向时是否需要持久化
                .storeDurably(false).build();
        CronTrigger trigger = TriggerBuilder.newTrigger()
                // 触发器名称和触发器分组 组合成触发器唯一标识
                .withIdentity("Trigger" + jobName, "Trigger" + groupName)
                // cron触发器时间设定
                .withSchedule(CronScheduleBuilder.cronSchedule(jobCron).inTimeZone(defaultTimeZone))
                .build();
        TriggerKey triggerKey = TriggerKey.triggerKey("Trigger" + jobName, "Trigger" + groupName);
        // 如果已经存在定时任务
        if (scheduler.checkExists(triggerKey)) {
            // 更新定时任务的cron
            scheduler.rescheduleJob(triggerKey, trigger);
        } else {
            // 添加定时任务
            scheduler.scheduleJob(jobDetail, trigger);
        }
    }

    /**
     * 删除定时任务
     * 
     * @param scheduler Quartz调度器
     * @param jobClass 任务类
     * @param groupName 任务分组
     * @param jobName 任务名
     * @throws SchedulerException 
     */
    private void deleteJob(Scheduler scheduler, String groupName, String jobName) throws SchedulerException {
        TriggerKey triggerKey = TriggerKey.triggerKey("Trigger" + jobName, "Trigger" + groupName);
        // 如果已经存在定时任务
        if (scheduler.checkExists(triggerKey)) {
            // 删除触发器,如果对应的任务没有其他的触发器关联并且Durably=false的时候,同时删除对应的任务
            scheduler.unscheduleJob(triggerKey);
        }
    }
}

     3.5 Job1用来实现具体的任务逻辑,类名自己随便改,每个任务创建一个类

package com.study.quartz.task;

import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;

import com.study.quartz.service.IXXXService;

//禁止并发执行(Quartz不要并发地执行同一个job定义(这里指一个job类的多个实例))
@DisallowConcurrentExecution
public class Job1 extends QuartzJobBean {
    private static final Logger logger = LoggerFactory.getLogger(Job1.class);

    @Autowired
    private IXXXService iXXXService;

	@Override
	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		logger.info("【定时任务】Job1 启动");
        iXXXService.doSomething(null);//调用Service执行具体的逻辑
	}

}

     3.6 IXXXService的接口和Service实现类这里不做记载了,直接按自己的业务逻辑来

四.创建quartz的表

     因为集群版的quartz是把任务存到数据库里,所以需要创建一下quartz的表。创建表的SQL来自于quartz的jar包里,搜索一下maven目录,我这里的是D:\Program Files\eclipse-maven\repository\org\quartz-scheduler\quartz\2.3.2\quartz-2.3.2.jar 。文件内路径quartz-2.3.2.jar\org\quartz\impl\jdbcjobstore    。根据自己的数据库选择sql文件,我这里用的tables_mysql_innodb.sql

Springboot+Quartz集群配置_第1张图片

你可能感兴趣的:(Spring,Boot,JAVA,quartz,集群,spring,boot)