SpringBoot整合Quartz實(shí)現(xiàn)定時(shí)任務(wù)詳解
Quartz簡(jiǎn)介
Quartz 是一個(gè)開(kāi)源的作業(yè)調(diào)度框架,它完全由 Java 寫成,并設(shè)計(jì)用于 J2SE 和 J2EE 應(yīng)用中。它提供了巨大的靈活性而不犧牲簡(jiǎn)單性。你能夠用它來(lái)為執(zhí)行一個(gè)作業(yè)而創(chuàng)建簡(jiǎn)單的或復(fù)雜的調(diào)度。它有很多特征,如:數(shù)據(jù)庫(kù)支持,集群,插件,EJB 作業(yè)預(yù)構(gòu)建,JavaMail 及其它,支持 cron-like 表達(dá)式等等。
核心概念
主要有三個(gè)核心概念:調(diào)度器、任務(wù)和觸發(fā)器。三者關(guān)系簡(jiǎn)單來(lái)說(shuō)就是,調(diào)度器負(fù)責(zé)調(diào)度各個(gè)任務(wù),到了某個(gè)時(shí)刻或者過(guò)了一定時(shí)間,觸發(fā)器觸動(dòng)了,特定任務(wù)便啟動(dòng)執(zhí)行。
Scheduler
Scheduler(調(diào)度器),基于trigger(觸發(fā)器)的設(shè)定執(zhí)行job(任務(wù)),代表一個(gè)Quartz的獨(dú)立運(yùn)行容器,Trigger和JobDetail要注冊(cè)到Scheduler中才會(huì)生效,也就是讓調(diào)度器知道有哪些觸發(fā)器和任務(wù),才能進(jìn)行按規(guī)則進(jìn)行調(diào)度任務(wù)。
JobDetail
Quartz 中需要執(zhí)行的任務(wù)詳情,包括了任務(wù)的唯一標(biāo)識(shí)和具體要執(zhí)行的任務(wù),可以通過(guò) JobDataMap 往任務(wù)中傳遞數(shù)據(jù)
Job
Job(任務(wù)),封裝成JobDetail設(shè)置屬性。
其中有兩個(gè)重要注解
@DisallowConcurrentExecution :禁止并發(fā)的執(zhí)行同一個(gè)job定義的多個(gè)實(shí)例
@PersistJobDataAfterExecution:持久化JobDetail中的JobDataMap(對(duì)trigger中的DataMap無(wú)效)
Trigger
Trigger(觸發(fā)器),描述觸發(fā)Job執(zhí)行的時(shí)間觸發(fā)規(guī)則。有SimpleTrigger和CronTrigger兩個(gè)子類代表兩種方式,一種是每隔多少分鐘小時(shí)執(zhí)行,則用SimpleTrigger;另一種是日歷相關(guān)的重復(fù)時(shí)間間隔,如每天凌晨,每周星期一運(yùn)行的話,通過(guò)Cron表達(dá)式便可定義出復(fù)雜的調(diào)度方案。
SpringBoot整合Quartz
準(zhǔn)備數(shù)據(jù)庫(kù)表
不同版本的quartz使用的數(shù)據(jù)庫(kù)表不同,具體如下,選擇對(duì)應(yīng)版本即可
https://github.com/quartz-scheduler/quartz/tree/quartz-2.1.x

創(chuàng)建之后,表關(guān)系如圖所示

Maven相關(guān)依賴
<!--spring連接驅(qū)動(dòng)時(shí),如com.mysql.cj.jdbc.Driver使用-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--quartz依賴-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>配置文件
application.yml
spring:
datasource:
username: xxx
password: xxxxxx
url: jdbc:mysql://localhost:3306/qrtz_db?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
spring-quartz.properties
#===================================================================
#配置JobStore
#===================================================================#JobDataMaps是否都為String類型,默認(rèn)為false
org.quartz.jobStore.useProperties = false#表前綴
org.quartz.jobStore.tablePrefix = qrtz_#是否加入集群
org.quartz.jobStore.isClustered = true#調(diào)度實(shí)例失敗的檢查時(shí)間間隔 ms
org.quartz.jobStore.clusterCheckinInterval = 5000org.quartz.jobStore.txIsolationLevelReadCommitted = true
#數(shù)據(jù)保存方式為數(shù)據(jù)持久化
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX#數(shù)據(jù)庫(kù)代理類,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以滿足大部分?jǐn)?shù)據(jù)庫(kù)
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate#===================================================================
#配置Scheduler 調(diào)度器屬性配置
#===================================================================#調(diào)度標(biāo)識(shí)名 集群中每一個(gè)實(shí)例都必須使用相同的名稱
org.quartz.scheduler.instanceName = ClusterQuartz#ID設(shè)置為自動(dòng)獲取 每一個(gè)必須不同
org.quartz.scheduler.instanceId = AUTO#===================================================================
#配置ThreadPool
#===================================================================#線程池的實(shí)現(xiàn)類(一般使用SimpleThreadPool即可滿足幾乎所有的用戶)
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool#指定線程數(shù),一般設(shè)定為1-100之間的整數(shù),根據(jù)系統(tǒng)資源配置
org.quartz.threadPool.threadCount = 5#設(shè)置線程的優(yōu)先級(jí)(可以是Thread.MIN_PRIORITY(即1)和Thread.MAX_PRIORITY(10)之間的任何int)
org.quartz.threadPool.threadPriority = 5
quartz配置類
@Configuration
public class SchedulerConfig {
@Autowired
private DataSource dataSource;
@Bean
public Scheduler scheduler() throws IOException {
return schedulerFactoryBean().getScheduler();
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setSchedulerName("cluster_scheduler");
factory.setDataSource(dataSource);
factory.setApplicationContextSchedulerContextKey("application");
factory.setQuartzProperties(quartzProperties());
factory.setTaskExecutor(schedulerThreadPool());
factory.setStartupDelay(10);
return factory;
}
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/spring-quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
@Bean
public Executor schedulerThreadPool(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(8);
executor.setMaxPoolSize(8);
executor.setQueueCapacity(8);
return executor;
}
}創(chuàng)建任務(wù)類
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class QuartzJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
Thread.sleep(2000);
System.out.println(context.getScheduler().getSchedulerInstanceId());
System.out.println("taskName="+context.getJobDetail().getKey().getName());
System.out.println("執(zhí)行時(shí)間="+new Date());
} catch (Exception e) {
e.printStackTrace();
}
}
}創(chuàng)建監(jiān)聽(tīng)類
@Component
public class StartApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private Scheduler scheduler;
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
TriggerKey triggerKey = TriggerKey.triggerKey("trigger1","group1");
try {
Trigger trigger = scheduler.getTrigger(triggerKey);
if (trigger == null){
trigger = TriggerBuilder.newTrigger()
.withIdentity(triggerKey)
.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?"))
.startNow()
.build();
JobDetail jobDetail = JobBuilder.newJob(QuartzJob.class)
.withIdentity("job1","group1")
.build();
scheduler.scheduleJob(jobDetail,trigger);
scheduler.start();
}
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}運(yùn)行結(jié)果

可以看到每隔十秒執(zhí)行一次。
到此這篇關(guān)于SpringBoot整合Quartz實(shí)現(xiàn)定時(shí)任務(wù)詳解的文章就介紹到這了,更多相關(guān)SpringBoot Quartz內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot?整合?Quartz?定時(shí)任務(wù)框架詳解
- springboot整合xxl-job實(shí)現(xiàn)分布式定時(shí)任務(wù)的過(guò)程
- springboot整合Quartz實(shí)現(xiàn)動(dòng)態(tài)配置定時(shí)任務(wù)的方法
- 詳解SpringBoot開(kāi)發(fā)案例之整合定時(shí)任務(wù)(Scheduled)
- springboot整合quartz實(shí)現(xiàn)定時(shí)任務(wù)示例
- SpringBoot定時(shí)任務(wù)兩種(Spring Schedule 與 Quartz 整合 )實(shí)現(xiàn)方法
- SpringBoot整合定時(shí)任務(wù)的方法
相關(guān)文章
java實(shí)現(xiàn)簡(jiǎn)單的圖書管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單的圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
SpringBoot 快速實(shí)現(xiàn) api 加密的方法
在項(xiàng)目中,為了保證數(shù)據(jù)的安全,我們常常會(huì)對(duì)傳遞的數(shù)據(jù)進(jìn)行加密,常用的加密算法包括對(duì)稱加密(AES)和非對(duì)稱加密(RSA),本文給大家介紹SpringBoot 快速實(shí)現(xiàn) api 加密,感興趣的朋友一起看看吧2023-10-10
Mybatis注解方式完成輸入?yún)?shù)為list的SQL語(yǔ)句拼接方式
這篇文章主要介紹了Mybatis注解方式完成輸入?yún)?shù)為list的SQL語(yǔ)句拼接方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java構(gòu)建菜單樹的實(shí)現(xiàn)示例
本文主要介紹了Java構(gòu)建菜單樹的實(shí)現(xiàn)示例,像一級(jí)菜單,二級(jí)菜單,三級(jí)菜單甚至更多層級(jí)的菜單,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
最新IDEA?2022基于JVM極致優(yōu)化?IDEA啟動(dòng)速度的方法
這篇文章主要介紹了IDEA?2022最新版?基于?JVM極致優(yōu)化?IDEA?啟動(dòng)速度,需要的朋友可以參考下2022-08-08
Java分布式學(xué)習(xí)之Kafka消息隊(duì)列
Kafka是由Apache軟件基金會(huì)開(kāi)發(fā)的一個(gè)開(kāi)源流處理平臺(tái),由Scala和Java編寫。Kafka是一種高吞吐量的分布式發(fā)布訂閱消息系統(tǒng),它可以處理消費(fèi)者在網(wǎng)站中的所有動(dòng)作流數(shù)據(jù)2022-07-07
教你怎么用Java數(shù)組和鏈表實(shí)現(xiàn)棧
本篇文章為大家詳細(xì)介紹了怎么用Java數(shù)組和鏈表實(shí)現(xiàn)棧,文中有非常詳細(xì)的代碼示例及注釋,對(duì)正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下2021-05-05

