Spring Boot整合Quartz持久化到数据库

获取Sql文件

http://www.quartz-scheduler.org/downloads/
Spring Boot整合Quartz持久化到数据库_第1张图片
解压获取的sql文件,并在数据库中执行
Spring Boot整合Quartz持久化到数据库_第2张图片

代码编写

引入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-jdbcartifactId>
        <version>2.0.6.RELEASEversion>
    dependency>
    <dependency>
        <groupId>org.quartz-schedulergroupId>
        <artifactId>quartzartifactId>
        <version>2.3.0version>
    dependency>
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-context-supportartifactId>
    dependency>
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <scope>runtimescope>
    dependency>
    <dependency>
        <groupId>com.mchangegroupId>
        <artifactId>c3p0artifactId>
        <version>0.9.5.2version>
    dependency>
dependencies>

quartz.properties (这里只配置了部分)
如果不想使用quartz.properties,文章末尾提供了yml配置,只需修改部分即可,其他的不变。

#=======================================================
#调度器配置
#=======================================================
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.instanceName=project1QuartzScheduler
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
#=======================================================
#线程池配置
#=======================================================
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=5
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
#=======================================================
#JobStore配置
#=======================================================
org.quartz.jobStore.misfireThreshold=60000
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.tablePrefix=QRTZ_
org.quartz.jobStore.dataSource=myDS
#=======================================================
#数据库配置
#=======================================================
org.quartz.dataSource.myDS.driver= com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL= jdbc:mysql:///quartz?characterEncoding=utf8&serverTimezone=UTC
org.quartz.dataSource.myDS.user= root
org.quartz.dataSource.myDS.password=151310
org.quartz.dataSource.myDS.maxConnections=5

这里给出大部分配置的详解(忽略了官方不推荐的配置)
官方配置

#========================================================================#
#                                 主配置                                 #
#========================================================================#
#调度器实例名称——用于在同一程序中使用多个实例时区分调度器#
#集群中同一调度器名称必须一致#
org.quartz.scheduler.instanceName
#调度器唯一,可以使用AUTO自动生成ID#
org.quartz.scheduler.instanceId
#可以实现InstanceIdGenerator接口,指定生成ID策略(instanceId需为AUTO)#
org.quartz.scheduler.instanceIdGenerator.class
#调度程序线程名称#
org.quartz.scheduler.threadName
#调度程序是否以守护线程运行#
org.quartz.scheduler.makeSchedulerThreadDaemon
#使用的JobFactory的类名#
org.quartz.scheduler.jobFactory.class
#调度程序节点一次允许获取(用于触发)的最大触发器数量#
org.quartz.scheduler.batchTriggerAcquisitionMaxCount
#========================================================================#
#                                线程池配置                              #
#========================================================================#
#使用的线程池实现的名称#
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
#线程数#
org.quartz.threadPool.threadCount
#线程优先级,默认为5#
org.quartz.threadPool.threadPriority
#========================================================================#
#                             全局监视器配置                             #
#========================================================================#
org.quartz.triggerListener.NAME.class
org.quartz.triggerListener.NAME.propName
org.quartz.triggerListener.NAME.prop2Name
org.quartz.jobListener.NAME.class
org.quartz.jobListener.NAME.propName
org.quartz.jobListener.NAME.prop2Name
#========================================================================#
#                             RAMJobStore配置                            #
#========================================================================#
#将调度程序的JobStore设置为RAMJobStore#
org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
#RAMJobStore可以通过下面属性进行调优#
#调度程序将容忍触发器通过下一次触发时间的毫秒数,然后才被认为是未触发,默认60000#
org.quartz.jobStore.misfireThreshold
#========================================================================#
#                           JDBC-JobStoreTX配置                          #
#========================================================================#
#驱动程序代表理解不同数据库系统的特定方言,许多数据库使用StdJDBCDelegate#
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#配置属性文件中定义的数据源的名称#
org.quartz.jobStore.dataSource
#Quartz表的前缀#
org.quartz.jobStore.tablePrefix
#JobDataMaps中的所有值都是字符串#
org.quartz.jobStore.useProperties
#调度程序将容忍触发器通过下一次触发时间的毫秒数,然后才被认为是未触发,默认60000#
org.quartz.jobStore.misfireThreshold
#是否为集群。如果多个Quartz实例使用同一数据库,必须为true,否则会造成严重破坏#
org.quartz.jobStore.isClustered
#此实例与集群的其他实例签入的频率(毫秒)。影响检测失败实例的速度#
org.quartz.jobStore.clusterCheckinInterval
#为true时Quartz在从数据源获得的连接上不要调用setAutoCommit(false)#
org.quartz.jobStore.dontSetAutoCommitFalse
#SQL字符串,它选择LOCKS表中的一行,并在该行上放置一个锁#
#默认SELECT * FROM {0}LOCKS WHERE SCHED_NAME = {1} AND LOCK_NAME = ?#
#{0}:TABLE_PREFIX {1}:调度程序的名称
org.quartz.jobStore.selectWithLockSQL
#为true时Quartz在JDBC连接上调用setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE)#
org.quartz.jobStore.txIsolationLevelSerializable
#========================================================================#
#                            DataSources配置                             #
#========================================================================#
#数据库JDBC驱动程序类#
org.quartz.dataSource.NAME.driver
#连接quartz数据库的url#
org.quartz.dataSource.NAME.URL
#用户名#
org.quartz.dataSource.NAME.user
#密码#
org.quartz.dataSource.NAME.password
#数据源创建的最大连接数#
org.quartz.dataSource.NAME.maxConnections

注意

  • myDS不要改
  • quartz是我的数据库,注意改为你的
  • QRTZ_是表的前缀

创建quartz配置文件

package com.dfyang.quartz.config;

import org.quartz.Scheduler;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

@Configuration
public class QuartzConfig {
	@Autowired
	private JobFactory jobFactory;
	
	@Autowired
	private AutowireCapableBeanFactory  capableBeanFactory;
	
	/**
	 * 当触发器触发时,与之关联的任务被Scheduler中配置的JobFactory实例化,也就是每触发一次,就会创建一个任务的实例化对象
	 * (如果缺省)则调用Job类的newInstance方法生成一个实例
	 * (这里选择自定义)并将创建的Job实例化交给IoC管理
	 * @return
	 */
	@Bean
	public JobFactory jobFactory() {
		return new AdaptableJobFactory() {
			@Override
			protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
				Object jobInstance = super.createJobInstance(bundle);
				capableBeanFactory.autowireBean(jobInstance);
				return jobInstance;
			}
		};
	}
	
	@Bean
	public SchedulerFactoryBean schedulerFactoryBean() {
		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
		schedulerFactoryBean.setJobFactory(jobFactory);
		//延迟启动
		schedulerFactoryBean.setStartupDelay(1);
		schedulerFactoryBean.setConfigLocation(new ClassPathResource("/quartz.properties"));
		return schedulerFactoryBean;
	}
	
	@Bean
	public Scheduler scheduler() {
		return schedulerFactoryBean().getScheduler();
	}
}

创建任务

package com.dfyang.quartz.controller;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class HelloJob extends QuartzJobBean {

	@Override
	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		System.err.println("hello world");
	}
}

创建quartz-service接口

package com.dfyang.quartz.service;

import org.springframework.stereotype.Service;

@Service
public interface QuartzService {
    /**
     * 新增一个定时任务
     * @param jName 任务名称
     * @param jGroup 任务组
     * @param tName 触发器名称
     * @param tGroup 触发器组
     * @param cron cron表达式
     */
    void addJob(String jName, String jGroup, String tName, String tGroup, String cron);

    /**
     * 暂停定时任务
     * @param jName 任务名
     * @param jGroup 任务组
     */
    void pauseJob(String jName, String jGroup);

    /**
     * 继续定时任务
     * @param jName 任务名
     * @param jGroup 任务组
     */
    void resumeJob(String jName, String jGroup);

    /**
     * 删除定时任务
     * @param jName 任务名
     * @param jGroup 任务组
     */
    void deleteJob(String jName, String jGroup);
}

创建quartz-service实现

package com.dfyang.quartz.service.impl;

import com.dfyang.quartz.controller.HelloJob;
import com.dfyang.quartz.service.QuartzService;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class QuartzServiceImpl implements QuartzService {

    @Autowired
    private Scheduler scheduler;

    /**
     * 新增一个定时任务
     * @param jName 任务名称
     * @param jGroup 任务组
     * @param tName 触发器名称
     * @param tGroup 触发器组
     * @param cron cron表达式
     */
    @Override
    public void addJob(String jName, String jGroup, String tName, String tGroup, String cron) {
        try {
            JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
                    .withIdentity(jName, jGroup)
                    .build();
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(tName, tGroup)
                    .startNow()
                    .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                    .build();
            scheduler.start();
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 暂停定时任务
     * @param jName 任务名
     * @param jGroup 任务组
     */
    @Override
    public void pauseJob(String jName, String jGroup) {
        try {
            scheduler.pauseJob(JobKey.jobKey(jName, jGroup));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 继续定时任务
     * @param jName 任务名
     * @param jGroup 任务组
     */
    @Override
    public void resumeJob(String jName, String jGroup) {
        try {
            scheduler.resumeJob(JobKey.jobKey(jName, jGroup));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除定时任务
     * @param jName 任务名
     * @param jGroup 任务组
     */
    @Override
    public void deleteJob(String jName, String jGroup) {
        try {
            scheduler.deleteJob(JobKey.jobKey(jName, jGroup));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

创建测试controller

package com.dfyang.quartz.controller;

import com.dfyang.quartz.service.QuartzService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class QuartzController {

    @Autowired
    private QuartzService quartzService;

    /**
     * 新增任务
     */
    @GetMapping("/insert")
    public String insertTask(String jName, String jGroup, String tName, String tGroup, String cron) {
        quartzService.addJob(jName, jGroup, tName, tGroup, cron);
        return "添加成功!";
    }

    /**
     * 暂停任务
     */
    @GetMapping("/pause")
    public String pauseTask(String jName, String jGroup) {
        quartzService.pauseJob(jName, jGroup);
        return "暂停成功!";
    }

    /**
     * 继续任务
     */
    @GetMapping("/resume")
    public String resumeTask(String jName, String jGroup) {
        quartzService.resumeJob(jName, jGroup);
        return "继续成功!";
    }

    /**
     * 删除任务
     */
    @GetMapping("/delete")
    public String deleteTask(String jName, String jGroup) {
        quartzService.deleteJob(jName, jGroup);
        return "删除成功!";
    }

}

启动项目
在这里插入图片描述
测试新增
http://localhost:8080/insert?jName=testJob&jGroup=test&tName=testTrigger&tGroup=test&cron=0,10,20,30,40,50 * * * * ?

在这里插入图片描述
在这里插入图片描述
Spring Boot整合Quartz持久化到数据库_第3张图片
如果重新启动项目,这时创建的任务仍然能够执行,因为已经持久化到了数据库。
其他可以自行测试,因为测试简单,这里没写了。

另一种配置

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-quartzartifactId>
    <version>2.1.1.RELEASEversion>
dependency>

application-quartz.yml

spring:
  quartz:
    properties:
      org:
        quartz:
          scheduler:
            instanceName: DefaultQuartzScheduler
            instanceId: AUTO
            rmi:
              export: false
              proxy: false
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            tablePrefix: QRTZ_
            isClustered: false
            useProperties: false
            misfireThreshold: 60000
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true
          dataSource:
            myDS:
              URL: jdbc:mysql:///quartz?characterEncoding=utf8&serverTimezone=UTC
              user: root
              password: 151310
              driver: com.mysql.jdbc.Driver
              maxConnections: 5
    job-store-type: jdbc

最后把config中使用配置文件去掉即可,其他的可以不用改。

package com.dfyang.quartz.config;

import org.quartz.Scheduler;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

@Configuration
public class QuartzConfig {
	@Autowired
	private JobFactory jobFactory;
	
	@Autowired
	private AutowireCapableBeanFactory  capableBeanFactory;
	
	/**
	 * 当触发器触发时,与之关联的任务被Scheduler中配置的JobFactory实例化,也就是每触发一次,就会创建一个任务的实例化对象
	 * (如果缺省)则调用Job类的newInstance方法生成一个实例
	 * (这里选择自定义)并将创建的Job实例化交给IoC管理
	 * @return
	 */
	@Bean
	public JobFactory jobFactory() {
		return new AdaptableJobFactory() {
			@Override
			protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
				Object jobInstance = super.createJobInstance(bundle);
				capableBeanFactory.autowireBean(jobInstance);
				return jobInstance;
			}
		};
	}
	
	@Bean
	public SchedulerFactoryBean schedulerFactoryBean() {
		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
		schedulerFactoryBean.setJobFactory(jobFactory);
		//延迟启动
		schedulerFactoryBean.setStartupDelay(1);
		return schedulerFactoryBean;
	}
	
	@Bean
	public Scheduler scheduler() {
		return schedulerFactoryBean().getScheduler();
	}
}

你可能感兴趣的:(Spring Boot整合Quartz持久化到数据库)