Spring Boot整合Quartz持久化到数据库_selectwithlocksql_DFYoung的博客-程序员秘密

获取Sql文件

http://www.quartz-scheduler.org/downloads/
在这里插入图片描述
解压获取的sql文件,并在数据库中执行
在这里插入图片描述

代码编写

引入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
        <version>2.0.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.2</version>
    </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 * * * * ?

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

另一种配置

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

application.properties

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/quartz?characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=151310
spring.quartz.properties.org.quartz.scheduler.instanceName=DefaultQuartzScheduler
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
spring.quartz.properties.org.quartz.scheduler.rmi.export=false
spring.quartz.properties.org.quartz.scheduler.rmi.proxy=false
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_
spring.quartz.properties.org.quartz.jobStore.isClustered=false
spring.quartz.properties.org.quartz.jobStore.useProperties=false
spring.quartz.properties.org.quartz.jobStore.misfireThreshold=60000
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
spring.quartz.properties.org.quartz.threadPool.threadCount=10
spring.quartz.properties.org.quartz.threadPool.threadPriority=5
spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
spring.quartz.properties.org.quartz.dataSource.myDS.URL=jdbc:mysql:///quartz?characterEncoding=utf8&serverTimezone=UTC
spring.quartz.properties.org.quartz.dataSource.myDS.user=root
spring.quartz.properties.org.quartz.dataSource.myDS.password=151310
spring.quartz.properties.org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver
spring.quartz.properties.org.quartz.dataSource.myDS.maxConnections=5
spring.quartz.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();
	}
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dh554112075/article/details/90727171

智能推荐

最新中文分词方面的论文和数据集_中文分词数据集_Mr.Jk.Zhang的博客-程序员秘密

Chinese Word SegmentationTaskChinese word segmentation is the task ofsplitting Chinese text (a sequence of Chinese characters)into words.Example:'上海浦东开发与建设同步' → ['上海', '浦东', '开发', ‘与', ’建设', '同步...

python公历转农历_有没有 python3 可用的农历转公历的包?_lesliu的博客-程序员秘密

lifulinghan2018-08-09 10:09:32 +08:00有啊,你可以试一下 sxtwl,pip install sxtwlimport sxtwl#日历中文索引ymc = [u"十一", u"十二", u"正", u"二", u"三", u"四", u"五", u"六", u"七", u"八", u"九", u"十" ]rmc = [u"初一", u"初二", u"初三", u...

C++趣味问题丨如何利用贪心算法实现搬水果问题?_Emily-C的博客-程序员秘密

这篇文章主要介绍了C++ 搬水果贪心算法实现代码的相关资料,需要的朋友可以参考下。C++ 搬水果贪心算法实现代码题目描述:在一个果园里,小明已经将所有的水果打了下来,并按水果的不同种类分成了若干堆,小明决定把所有的水果合成一堆。每一次合并,小明可以把两堆水果合并到一起,消耗的体力等于两堆水果的重量之和。当然经过 n‐1 次合并之后,就变成一堆了。小明在合并水果时总共消耗的体力等于每次合并所耗体力之和。假定每个水果重量都为 1,并且已知水果的种类数和每种水果的数目,你的任务是设计出合.

spark配置代理_spark 代理_chg1226的博客-程序员秘密

主要是spark.driver.extraJavaOptions和spark.executor.extraJavaOptions两个参数可以写到配置文件里,spark.driver.extraJavaOptions &amp;quot;-Dhttp.proxyHost=&amp;amp;lt;&amp;amp;gt; -Dhttp.proxyProt=&amp;amp;lt;&amp;amp;gt; -Dhttps.proxyHost=&amp;amp;lt;&amp;amp;gt; -Dht

android关闭软键盘和弹出键盘将布局顶上去_android 软键盘窗口最前显示_zane_xiao的博客-程序员秘密

**- 关闭软键盘**在清单文件中,给当前activity设置键盘属性 android:windowSoftInputMode="stateAlwaysHidden" //在activity设置布局以后,添加 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); 2.

逍遥模拟器安卓7.1离线安装xposed_逆向三十六计的博客-程序员秘密

以下操作都是基于安卓7.11.打开逍遥模拟器应用市场,下载RE文件管理器。2、下载离线安装文件并解压,解压后有如下图所示文件。3.将终端模拟器拖进安卓模拟器进行安装。4.打开共享文件夹,将第二部解压出来的xposed文件夹拷贝到共享文件夹。5.打开RE文件管理器,找到共享文件夹下的xposed,鼠标左键长按,然后点击右上角的复制按钮。6.然后切换到左边根目录并进入system目录,点击右下角粘贴按钮。7.回到模拟器主页,打开终端模拟器,输入以下命令并回车,完成后重启模拟器。

随便推点

C++编程思想 第1卷 第8章 常量 函数参数和返回值 传递和返回地址_eyetired的博客-程序员秘密

如果传递或返回一个地址 一个指针或一个引用,客户程序员去取地址并修改初值是可能的。如果指针或引用成为const,就会阻止这类事的发生无论什么时候传递一个地址给一个函数,都应该尽可能用const修饰它时候选择返回一个指向const的指针或者引用,取决于想让客户程序员用它做什么如何使用const指针作为函数参数和返回值//: C08:ConstPointer.cpp// Fr...

MybatisPlus 之 PaginationInterceptor 扩展配置bean_Mynah886的博客-程序员秘密

package com.dcits.branch.cloud.tran.configuration;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.core.parser.ISqlParser;import com.baomidou.mybatisplus.extension...

我花了一年时间研究不确定性估算,写下了这份最全指南_程序员之家_的博客-程序员秘密

微信又改版了,为了方便第一时间看到我们的推送,请按照下列操作,设置“置顶”:点击上方蓝色字体“程序员之家”-点击右上角“…”-点击“设为星标”。可以啦,让我们继续相互陪伴...

数据挖掘学习笔记(一)_BerMaker的博客-程序员秘密

1        引论1.1   为什么进行数据挖掘1.1.1           迈向信息时代数据挖掘把大型数据集转换成知识,帮助我们应对当代的全球性挑战。1.1.2           数据挖掘是信息技术的进化数据挖掘可以看做信息技术自然进化的结果。数据库和数据管理产业在一些关键功能的开发上不断发展:数据收集和数据库创建(包括数据存储和检索、数据库事务处理)和高级数据分析(

每日思考第 68 期:如何致富,不靠运气2_蜗牛互联网的博客-程序员秘密

每日思考专栏每周日更新,本期覆盖 20210301~20210307。本期继续谈谈美国风险投资家 Naval 关于致富的观点。210301:承担责任【承担责任】美国风险投资家 Naval ...

推荐文章

热门文章

相关标签