溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringBoot2整合QuartJob如何實現(xiàn)定時器實時管理功能

發(fā)布時間:2021-09-27 15:39:41 來源:億速云 閱讀:159 作者:小新 欄目:編程語言

這篇文章主要介紹了SpringBoot2整合QuartJob如何實現(xiàn)定時器實時管理功能,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

一、QuartJob簡介

1、一句話描述

Quartz是一個完全由java編寫的開源作業(yè)調(diào)度框架,形式簡易,功能強(qiáng)大。

2、核心API

(1)、Scheduler

代表一個 Quartz 的獨立運(yùn)行容器,Scheduler 將 Trigger 綁定到特定 JobDetail, 這樣當(dāng) Trigger 觸發(fā)時, 對應(yīng)的 Job 就會被調(diào)度。

(2)、Trigger

描述 Job 執(zhí)行的時間觸發(fā)規(guī)則。主要有 SimpleTrigger 和 CronTrigger 兩個子類,通過一個 TriggerKey 唯一標(biāo)識。

(3)、Job

定義一個任務(wù),規(guī)定了任務(wù)是執(zhí)行時的行為。JobExecutionContext 提供了調(diào)度器的上下文信息,Job 的數(shù)據(jù)可從 JobDataMap 中獲取。

(4)、JobDetail

Quartz 在每次執(zhí)行 Job 時,都重新創(chuàng)建一個 Job 實例,所以它不直接接受一個 Job 的實例,相反它接收一個 Job 實現(xiàn)類。描述 Job 的實現(xiàn)類及其它相關(guān)的靜態(tài)信息,如 Job 名字、描述等。

二、與SpringBoot2.0 整合

1、項目結(jié)構(gòu)

版本描述

spring-boot:2.1.3.RELEASEquart-job:2.3.0

2、定時器配置

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.quartz.SchedulerFactoryBean;import javax.sql.DataSource;import java.util.Properties;@Configurationpublic class ScheduleConfig { @Bean public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) { // Quartz參數(shù)配置 Properties prop = new Properties(); // Schedule調(diào)度器的實體名字 prop.put("org.quartz.scheduler.instanceName", "HuskyScheduler"); // 設(shè)置為AUTO時使用,默認(rèn)的實現(xiàn)org.quartz.scheduler.SimpleInstanceGenerator是基于主機(jī)名稱和時間戳生成。 prop.put("org.quartz.scheduler.instanceId", "AUTO"); // 線程池配置 prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); prop.put("org.quartz.threadPool.threadCount", "20"); prop.put("org.quartz.threadPool.threadPriority", "5"); // JobStore配置:Scheduler在運(yùn)行時用來存儲相關(guān)的信息 // JDBCJobStore和JobStoreTX都使用關(guān)系數(shù)據(jù)庫來存儲Schedule相關(guān)的信息。 // JobStoreTX在每次執(zhí)行任務(wù)后都使用commit或者rollback來提交更改。 prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); // 集群配置:如果有多個調(diào)度器實體的話則必須設(shè)置為true prop.put("org.quartz.jobStore.isClustered", "true"); // 集群配置:檢查集群下的其他調(diào)度器實體的時間間隔 prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); // 設(shè)置一個頻度(毫秒),用于實例報告給集群中的其他實例 prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); // 觸發(fā)器觸發(fā)失敗后再次觸犯的時間間隔 prop.put("org.quartz.jobStore.misfireThreshold", "12000"); // 數(shù)據(jù)庫表前綴 prop.put("org.quartz.jobStore.tablePrefix", "qrtz_"); // 從 LOCKS 表查詢一行并對這行記錄加鎖的 SQL 語句 prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); // 定時器工廠配置 SchedulerFactoryBean factory = new SchedulerFactoryBean(); factory.setDataSource(dataSource); factory.setQuartzProperties(prop); factory.setSchedulerName("HuskyScheduler"); factory.setStartupDelay(30); factory.setApplicationContextSchedulerContextKey("applicationContextKey"); // 可選,QuartzScheduler 啟動時更新己存在的Job factory.setOverwriteExistingJobs(true); // 設(shè)置自動啟動,默認(rèn)為true factory.setAutoStartup(true); return factory; }}

3、定時器管理工具

import com.quart.job.entity.ScheduleJobBean;import org.quartz.*;/** * 定時器工具類 */public class ScheduleUtil { private ScheduleUtil (){} private static final String SCHEDULE_NAME = "HUSKY_" ; /** * 觸發(fā)器 KEY */ public static TriggerKey getTriggerKey(Long jobId){ return TriggerKey.triggerKey(SCHEDULE_NAME+jobId) ; } /** * 定時器 Key */ public static JobKey getJobKey (Long jobId){ return JobKey.jobKey(SCHEDULE_NAME+jobId) ; } /** * 表達(dá)式觸發(fā)器 */ public static CronTrigger getCronTrigger (Scheduler scheduler,Long jobId){ try {  return (CronTrigger)scheduler.getTrigger(getTriggerKey(jobId)) ; } catch (SchedulerException e){  throw new RuntimeException("getCronTrigger Fail",e) ; } } /** * 創(chuàng)建定時器 */ public static void createJob (Scheduler scheduler, ScheduleJobBean scheduleJob){ try {  // 構(gòu)建定時器  JobDetail jobDetail = JobBuilder.newJob(TaskJobLog.class).withIdentity(getJobKey(scheduleJob.getJobId())).build() ;  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder   .cronSchedule(scheduleJob.getCronExpression())   .withMisfireHandlingInstructionDoNothing() ;  CronTrigger trigger = TriggerBuilder.newTrigger()   .withIdentity(getTriggerKey(scheduleJob.getJobId()))   .withSchedule(scheduleBuilder).build() ;  jobDetail.getJobDataMap().put(ScheduleJobBean.JOB_PARAM_KEY,scheduleJob);  scheduler.scheduleJob(jobDetail,trigger) ;  // 如果該定時器處于暫停狀態(tài)  if (scheduleJob.getStatus() == 1){  pauseJob(scheduler,scheduleJob.getJobId()) ;  } } catch (SchedulerException e){  throw new RuntimeException("createJob Fail",e) ; } } /** * 更新定時任務(wù) */ public static void updateJob(Scheduler scheduler, ScheduleJobBean scheduleJob) { try {  // 構(gòu)建定時器  TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())   .withMisfireHandlingInstructionDoNothing();  CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());  trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();  trigger.getJobDataMap().put(ScheduleJobBean.JOB_PARAM_KEY, scheduleJob);  scheduler.rescheduleJob(triggerKey, trigger);  // 如果該定時器處于暫停狀態(tài)  if(scheduleJob.getStatus() == 1){  pauseJob(scheduler, scheduleJob.getJobId());  } } catch (SchedulerException e) {  throw new RuntimeException("updateJob Fail",e) ; } } /** * 停止定時器 */ public static void pauseJob (Scheduler scheduler,Long jobId){ try {  scheduler.pauseJob(getJobKey(jobId)); } catch (SchedulerException e){  throw new RuntimeException("pauseJob Fail",e) ; } } /** * 恢復(fù)定時器 */ public static void resumeJob (Scheduler scheduler,Long jobId){ try {  scheduler.resumeJob(getJobKey(jobId)); } catch (SchedulerException e){  throw new RuntimeException("resumeJob Fail",e) ; } } /** * 刪除定時器 */ public static void deleteJob (Scheduler scheduler,Long jobId){ try {  scheduler.deleteJob(getJobKey(jobId)); } catch (SchedulerException e){  throw new RuntimeException("deleteJob Fail",e) ; } } /** * 執(zhí)行定時器 */ public static void run (Scheduler scheduler, ScheduleJobBean scheduleJob){ try {  JobDataMap dataMap = new JobDataMap() ;  dataMap.put(ScheduleJobBean.JOB_PARAM_KEY,scheduleJob);  scheduler.triggerJob(getJobKey(scheduleJob.getJobId()),dataMap); } catch (SchedulerException e){  throw new RuntimeException("run Fail",e) ; } }}

4、定時器執(zhí)行和日志

import com.quart.job.entity.ScheduleJobBean;import com.quart.job.entity.ScheduleJobLogBean;import com.quart.job.service.ScheduleJobLogService;import org.quartz.JobExecutionContext;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.scheduling.quartz.QuartzJobBean;import java.lang.reflect.Method;import java.util.Date;/** * 定時器執(zhí)行日志記錄 */public class TaskJobLog extends QuartzJobBean { private static final Logger LOG = LoggerFactory.getLogger(TaskJobLog.class) ; @Override protected void executeInternal(JobExecutionContext context) { ScheduleJobBean jobBean = (ScheduleJobBean)context.getMergedJobDataMap().get(ScheduleJobBean.JOB_PARAM_KEY) ; ScheduleJobLogService scheduleJobLogService = (ScheduleJobLogService)SpringContextUtil.getBean("scheduleJobLogService") ; // 定時器日志記錄 ScheduleJobLogBean logBean = new ScheduleJobLogBean () ; logBean.setJobId(jobBean.getJobId()); logBean.setBeanName(jobBean.getBeanName()); logBean.setParams(jobBean.getParams()); logBean.setCreateTime(new Date()); long beginTime = System.currentTimeMillis() ; try {  // 加載并執(zhí)行定時器的 run 方法  Object target = SpringContextUtil.getBean(jobBean.getBeanName());  Method method = target.getClass().getDeclaredMethod("run", String.class);  method.invoke(target, jobBean.getParams());  long executeTime = System.currentTimeMillis() - beginTime;  logBean.setTimes((int)executeTime);  logBean.setStatus(0);  LOG.info("定時器 === >> "+jobBean.getJobId()+"執(zhí)行成功,耗時 === >> " + executeTime); } catch (Exception e){  // 異常信息  long executeTime = System.currentTimeMillis() - beginTime;  logBean.setTimes((int)executeTime);  logBean.setStatus(1);  logBean.setError(e.getMessage()); } finally {  scheduleJobLogService.insert(logBean) ; } }}

三、定時器服務(wù)封裝

1、定時器初始化

@Servicepublic class ScheduleJobServiceImpl implements ScheduleJobService { @Resource private Scheduler scheduler ; @Resource private ScheduleJobMapper scheduleJobMapper ; /** * 定時器初始化 */ @PostConstruct public void init (){ ScheduleJobExample example = new ScheduleJobExample() ; List<ScheduleJobBean> scheduleJobBeanList = scheduleJobMapper.selectByExample(example) ; for (ScheduleJobBean scheduleJobBean : scheduleJobBeanList) {  CronTrigger cronTrigger = ScheduleUtil.getCronTrigger(scheduler,scheduleJobBean.getJobId()) ;  if (cronTrigger == null){  ScheduleUtil.createJob(scheduler,scheduleJobBean);  } else {  ScheduleUtil.updateJob(scheduler,scheduleJobBean);  } } }}

2、添加定時器

@Override@Transactional(rollbackFor = Exception.class)public int insert(ScheduleJobBean record) { ScheduleUtil.createJob(scheduler,record); return scheduleJobMapper.insert(record);}

3、立即執(zhí)行一次定時器

@Override@Transactional(rollbackFor = Exception.class)public void run(Long jobId) { ScheduleJobBean scheduleJobBean = scheduleJobMapper.selectByPrimaryKey(jobId) ; ScheduleUtil.run(scheduler,scheduleJobBean);}

4、更新定時器

@Override@Transactional(rollbackFor = Exception.class)public int updateByPrimaryKeySelective(ScheduleJobBean record) { ScheduleUtil.updateJob(scheduler,record); return scheduleJobMapper.updateByPrimaryKeySelective(record);}

5、停止定時器

@Override@Transactional(rollbackFor = Exception.class)public void pauseJob(Long jobId) { ScheduleJobBean scheduleJobBean = scheduleJobMapper.selectByPrimaryKey(jobId) ; ScheduleUtil.pauseJob(scheduler,jobId); scheduleJobBean.setStatus(1); scheduleJobMapper.updateByPrimaryKeySelective(scheduleJobBean) ;}

6、恢復(fù)定時器

@Override@Transactional(rollbackFor = Exception.class)public void resumeJob(Long jobId) { ScheduleJobBean scheduleJobBean = scheduleJobMapper.selectByPrimaryKey(jobId) ; ScheduleUtil.resumeJob(scheduler,jobId); scheduleJobBean.setStatus(0); scheduleJobMapper.updateByPrimaryKeySelective(scheduleJobBean) ;}

7、刪除定時器

@Override@Transactional(rollbackFor = Exception.class)public void delete(Long jobId) { ScheduleUtil.deleteJob(scheduler, jobId); scheduleJobMapper.deleteByPrimaryKey(jobId) ;}

四、配置一個測試的定時器

1、定時接口封裝

public interface TaskService { void run(String params);}

2、測試定時器

@Component("getTimeTask")public class GetTimeTask implements TaskService { private static final Logger LOG = LoggerFactory.getLogger(GetTimeTask.class.getName()) ; private static final SimpleDateFormat format =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ; @Override public void run(String params) { LOG.info("Params === >> " + params); LOG.info("當(dāng)前時間::::"+format.format(new Date())); }}

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“SpringBoot2整合QuartJob如何實現(xiàn)定時器實時管理功能”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI