Spring Boot中實現(xiàn)定時任務應用實踐
前言
在Spring Boot中實現(xiàn)定時任務功能,可以通過Spring自帶的定時任務調(diào)度,也可以通過集成經(jīng)典開源組件Quartz實現(xiàn)任務調(diào)度。
本文將詳細介紹關于Spring Boot實現(xiàn)定時任務應用的相關內(nèi)容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。
一、Spring定時器
1、cron表達式方式
使用自帶的定時任務,非常簡單,只需要像下面這樣,加上注解就好,不需要像普通定時任務框架那樣繼承任何定時處理接口 ,簡單示例代碼如下:
package com.power.demo.scheduledtask.simple;
import com.power.demo.util.DateTimeUtil;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
@EnableScheduling
public class SpringTaskA {
/**
* CRON表達式參考:http://cron.qqe2.com/
**/
@Scheduled(cron = "*/5 * * * * ?", zone = "GMT+8:00")
private void timerCron() {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(String.format("(timerCron)%s 每隔5秒執(zhí)行一次,記錄日志", DateTimeUtil.fmtDate(new Date())));
}
}
SpringTaskA
上述代碼中,在一個類上添加@EnableScheduling注解,在方法上加上@Scheduled,配置下 cron 表達式,一個最最簡單的cron定時任務就完成了。cron表達式的各個組成部分,可以參考下面:
@Scheduled(cron = "[Seconds] [Minutes] [Hours] [Day of month] [Month] [Day of week] [Year]")
2、fixedRate和fixedDelay
@Scheduled注解除了cron表達式,還有其他配置方式,比如fixedRate和fixedDelay,下面這個示例通過配置方式的不同,實現(xiàn)不同形式的定時任務調(diào)度,示例代碼如下:
package com.power.demo.scheduledtask.simple;
import com.power.demo.util.DateTimeUtil;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
@EnableScheduling
public class SpringTaskB {
/*fixedRate:上一次開始執(zhí)行時間點之后5秒再執(zhí)行*/
@Scheduled(fixedRate = 5000)
public void timerFixedRate() {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(String.format("(fixedRate)現(xiàn)在時間:%s", DateTimeUtil.fmtDate(new Date())));
}
/*fixedDelay:上一次執(zhí)行完畢時間點之后5秒再執(zhí)行*/
@Scheduled(fixedDelay = 5000)
public void timerFixedDelay() {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(String.format("(fixedDelay)現(xiàn)在時間:%s", DateTimeUtil.fmtDate(new Date())));
}
/*第一次延遲2秒后執(zhí)行,之后按fixedDelay的規(guī)則每5秒執(zhí)行一次*/
@Scheduled(initialDelay = 2000, fixedDelay = 5000)
public void timerInitDelay() {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(String.format("(initDelay)現(xiàn)在時間:%s", DateTimeUtil.fmtDate(new Date())));
}
}
SpringTaskB
注意一下主要區(qū)別:
@Scheduled(fixedRate = 5000) :上一次開始執(zhí)行時間點之后5秒再執(zhí)行
@Scheduled(fixedDelay = 5000) :上一次執(zhí)行完畢時間點之后5秒再執(zhí)行
@Scheduled(initialDelay=2000, fixedDelay=5000) :第一次延遲2秒后執(zhí)行,之后按fixedDelay的規(guī)則每5秒執(zhí)行一次
有時候,很多項目我們都需要配置好定時任務后立即執(zhí)行一次,initialDelay就可以不用配置了。
3、zone
@Scheduled注解還有一個熟悉的屬性zone,表示時區(qū),通常,如果不寫,定時任務將使用服務器的默認時區(qū);如果你的任務想在特定時區(qū)特定時間點跑起來,比如常見的多語言系統(tǒng)可能會定時跑腳本更新數(shù)據(jù),就可以設置一個時區(qū),如東八區(qū),就可以設置為:
zone = "GMT+8:00"
二、Quartz
Quartz是應用最為廣泛的開源任務調(diào)度框架之一,有很多公司都根據(jù)它實現(xiàn)自己的定時任務管理系統(tǒng)。Quartz提供了最常用的兩種定時任務觸發(fā)器,即SimpleTrigger和CronTrigger,本文以最廣泛使用的CronTrigger為例。
1、添加依賴
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency>
2、配置cron表達式
示例代碼需要,在application.properties文件中新增如下配置:
## Quartz定時job配置 job.taska.cron=*/3 * * * * ? job.taskb.cron=*/7 * * * * ? job.taskmail.cron=*/5 * * * * ?
其實,我們完全可以不用配置,直接在代碼里面寫或者持久化在DB中然后讀取也可以。
3、添加定時任務實現(xiàn)
任務1:
package com.power.demo.scheduledtask.quartz;
import com.power.demo.util.DateTimeUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.Date;
@DisallowConcurrentExecution
public class QuartzTaskA implements Job {
@Override
public void execute(JobExecutionContext var1) throws JobExecutionException {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(String.format("(QuartzTaskA)%s 每隔3秒執(zhí)行一次,記錄日志", DateTimeUtil.fmtDate(new Date())));
}
}
QuartzTaskA
任務2:
package com.power.demo.scheduledtask.quartz;
import com.power.demo.util.DateTimeUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.Date;
@DisallowConcurrentExecution
public class QuartzTaskB implements Job {
@Override
public void execute(JobExecutionContext var1) throws JobExecutionException {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(String.format("(QuartzTaskB)%s 每隔7秒執(zhí)行一次,記錄日志", DateTimeUtil.fmtDate(new Date())));
}
}
QuartzTaskB
定時發(fā)送郵件任務:
package com.power.demo.scheduledtask.quartz;
import com.power.demo.service.contract.MailService;
import com.power.demo.util.DateTimeUtil;
import com.power.demo.util.PowerLogger;
import org.joda.time.DateTime;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
@DisallowConcurrentExecution
public class MailSendTask implements Job {
@Autowired
private MailService mailService;
@Override
public void execute(JobExecutionContext var1) throws JobExecutionException {
System.out.println(String.format("(MailSendTask)%s 每隔5秒發(fā)送郵件", DateTimeUtil.fmtDate(new Date())));
try {
//Thread.sleep(1);
DateTime dtNow = new DateTime(new Date());
Date startTime = dtNow.minusMonths(1).toDate();//一個月前
Date endTime = dtNow.plusDays(1).toDate();
mailService.autoSend(startTime, endTime);
PowerLogger.info(String.format("發(fā)送郵件,開始時間:%s,結束時間:%s"
, DateTimeUtil.fmtDate(startTime), DateTimeUtil.fmtDate(endTime)));
} catch (Exception e) {
e.printStackTrace();
PowerLogger.info(String.format("發(fā)送郵件,出現(xiàn)異常:%s,結束時間:%s", e));
}
}
}
MailSendTask
實現(xiàn)任務看上去非常簡單,繼承Quartz的Job接口,重寫execute方法即可。
4、集成Quartz定時任務
怎么讓Spring自動識別初始化Quartz定時任務實例呢?這就需要引用Spring管理的Bean,向Spring容器暴露所必須的bean,通過定義Job Factory實現(xiàn)自動注入。
首先,添加Spring注入的Job Factory類:
package com.power.demo.scheduledtask.quartz.config;
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;
public final class AutowireBeanJobFactory extends SpringBeanJobFactory
implements ApplicationContextAware {
private transient AutowireCapableBeanFactory beanFactory;
/**
* Spring提供了一種機制讓你可以獲取ApplicationContext,即ApplicationContextAware接口
* 對于一個實現(xiàn)了ApplicationContextAware接口的類,Spring會實例化它的同時調(diào)用它的
* public voidsetApplicationContext(ApplicationContext applicationContext) throws BeansException;接口,
* 將該bean所屬上下文傳遞給它。
**/
@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;
}
}
AutowireBeanJobFactory
定義QuartzConfig:
package com.power.demo.scheduledtask.quartz.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@Configuration
public class QuartzConfig {
@Autowired
@Qualifier("quartzTaskATrigger")
private CronTriggerFactoryBean quartzTaskATrigger;
@Autowired
@Qualifier("quartzTaskBTrigger")
private CronTriggerFactoryBean quartzTaskBTrigger;
@Autowired
@Qualifier("mailSendTrigger")
private CronTriggerFactoryBean mailSendTrigger;
//Quartz中的job自動注入spring容器托管的對象
@Bean
public AutowireBeanJobFactory autoWiringSpringBeanJobFactory() {
return new AutowireBeanJobFactory();
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
scheduler.setJobFactory(autoWiringSpringBeanJobFactory()); //配置Spring注入的Job類
//設置CronTriggerFactoryBean,設定任務Trigger
scheduler.setTriggers(
quartzTaskATrigger.getObject(),
quartzTaskBTrigger.getObject(),
mailSendTrigger.getObject()
);
return scheduler;
}
}
QuartzConfig
接著配置job明細:
package com.power.demo.scheduledtask.quartz.config;
import com.power.demo.common.AppField;
import com.power.demo.scheduledtask.quartz.MailSendTask;
import com.power.demo.scheduledtask.quartz.QuartzTaskA;
import com.power.demo.scheduledtask.quartz.QuartzTaskB;
import com.power.demo.util.ConfigUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
@Configuration
public class TaskSetting {
@Bean(name = "quartzTaskA")
public JobDetailFactoryBean jobDetailAFactoryBean() {
//生成JobDetail
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setJobClass(QuartzTaskA.class); //設置對應的Job
factory.setGroup("quartzTaskGroup");
factory.setName("quartzTaskAJob");
factory.setDurability(false);
factory.setDescription("測試任務A");
return factory;
}
@Bean(name = "quartzTaskATrigger")
public CronTriggerFactoryBean cronTriggerAFactoryBean() {
String cron = ConfigUtil.getConfigVal(AppField.JOB_TASKA_CRON);
CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();
//設置JobDetail
stFactory.setJobDetail(jobDetailAFactoryBean().getObject());
stFactory.setStartDelay(1000);
stFactory.setName("quartzTaskATrigger");
stFactory.setGroup("quartzTaskGroup");
stFactory.setCronExpression(cron);
return stFactory;
}
@Bean(name = "quartzTaskB")
public JobDetailFactoryBean jobDetailBFactoryBean() {
//生成JobDetail
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setJobClass(QuartzTaskB.class); //設置對應的Job
factory.setGroup("quartzTaskGroup");
factory.setName("quartzTaskBJob");
factory.setDurability(false);
factory.setDescription("測試任務B");
return factory;
}
@Bean(name = "quartzTaskBTrigger")
public CronTriggerFactoryBean cronTriggerBFactoryBean() {
String cron = ConfigUtil.getConfigVal(AppField.JOB_TASKB_CRON);
CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();
//設置JobDetail
stFactory.setJobDetail(jobDetailBFactoryBean().getObject());
stFactory.setStartDelay(1000);
stFactory.setName("quartzTaskBTrigger");
stFactory.setGroup("quartzTaskGroup");
stFactory.setCronExpression(cron);
return stFactory;
}
@Bean(name = "mailSendTask")
public JobDetailFactoryBean jobDetailMailFactoryBean() {
//生成JobDetail
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setJobClass(MailSendTask.class); //設置對應的Job
factory.setGroup("quartzTaskGroup");
factory.setName("mailSendTaskJob");
factory.setDurability(false);
factory.setDescription("郵件發(fā)送任務");
return factory;
}
@Bean(name = "mailSendTrigger")
public CronTriggerFactoryBean cronTriggerMailFactoryBean() {
String cron = ConfigUtil.getConfigVal(AppField.JOB_TASKMAIL_CRON);
CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();
//設置JobDetail
stFactory.setJobDetail(jobDetailMailFactoryBean().getObject());
stFactory.setStartDelay(1000);
stFactory.setName("mailSendTrigger");
stFactory.setGroup("quartzTaskGroup");
stFactory.setCronExpression(cron);
return stFactory;
}
}
TaskSetting
最后啟動你的Spring Boot定時任務應用,一個完整的基于Quartz調(diào)度的定時任務就實現(xiàn)好了。
本文定時任務示例中,有一個定時發(fā)送郵件任務MailSendTask,下一篇將分享Spring Boot應用中以MongoDB作為存儲介質的簡易郵件系統(tǒng)。
擴展閱讀:
很多公司都會有自己的定時任務調(diào)度框架和系統(tǒng),在Spring Boot中如何整合Quartz集群,實現(xiàn)動態(tài)定時任務配置?
參考:
http://www.dhdzp.com/article/139591.htm
http://www.dhdzp.com/article/139597.htm
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
- SpringBoot定時任務兩種(Spring Schedule 與 Quartz 整合 )實現(xiàn)方法
- 詳解Spring Boot中使用@Scheduled創(chuàng)建定時任務
- 詳解SpringBoot 創(chuàng)建定時任務(配合數(shù)據(jù)庫動態(tài)執(zhí)行)
- 詳解Spring Boot 定時任務的實現(xiàn)方法
- spring-boot通過@Scheduled配置定時任務及定時任務@Scheduled注解的方法
- SpringBoot 定時任務遇到的坑
- springboot整合Quartz實現(xiàn)動態(tài)配置定時任務的方法
- springboot整合quartz實現(xiàn)定時任務示例
- spring boot整合quartz實現(xiàn)多個定時任務的方法
- 詳解SpringBoot開發(fā)案例之整合定時任務(Scheduled)
相關文章
Java圖書管理系統(tǒng),課程設計必用(源碼+文檔)
本系統(tǒng)采用Java,MySQL 作為系統(tǒng)數(shù)據(jù)庫,重點開發(fā)并實現(xiàn)了系統(tǒng)各個核心功能模塊,包括采編模塊、典藏模塊、基礎信息模塊、流通模塊、期刊模塊、查詢模塊、評論模塊、系統(tǒng)統(tǒng)計模塊以及幫助功能模塊2021-06-06
IDEA2022.1創(chuàng)建maven項目規(guī)避idea2022新建maven項目卡死無反應問題
這篇文章主要介紹了IDEA2022.1創(chuàng)建maven項目規(guī)避idea2022新建maven項目卡死無反應問題,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08
基于springMvc+hibernate的web application的構建
下面小編就為大家?guī)硪黄趕pringMvc+hibernate的web application的構建。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10

