javascript
SpringBoot2.0 整合 QuartJob ,实现定时器实时管理
一、QuartJob簡(jiǎn)介
1、一句話描述
Quartz是一個(gè)完全由java編寫(xiě)的開(kāi)源作業(yè)調(diào)度框架,形式簡(jiǎn)易,功能強(qiáng)大。
2、核心API
(1)、Scheduler
代表一個(gè) Quartz 的獨(dú)立運(yùn)行容器,Scheduler 將 Trigger 綁定到特定 JobDetail, 這樣當(dāng) Trigger 觸發(fā)時(shí), 對(duì)應(yīng)的 Job 就會(huì)被調(diào)度。
(2)、Trigger
描述 Job 執(zhí)行的時(shí)間觸發(fā)規(guī)則。主要有 SimpleTrigger 和 CronTrigger 兩個(gè)子類(lèi),通過(guò)一個(gè) TriggerKey 唯一標(biāo)識(shí)。
(3)、Job
定義一個(gè)任務(wù),規(guī)定了任務(wù)是執(zhí)行時(shí)的行為。JobExecutionContext 提供了調(diào)度器的上下文信息,Job 的數(shù)據(jù)可從 JobDataMap 中獲取。
(4)、JobDetail
Quartz 在每次執(zhí)行 Job 時(shí),都重新創(chuàng)建一個(gè) Job 實(shí)例,所以它不直接接受一個(gè) Job 的實(shí)例,相反它接收一個(gè) Job 實(shí)現(xiàn)類(lèi)。描述 Job 的實(shí)現(xiàn)類(lèi)及其它相關(guān)的靜態(tài)信息,如 Job 名字、描述等。
二、與SpringBoot2.0 整合
1、項(xiàng)目結(jié)構(gòu)
版本描述
2、定時(shí)器配置
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; @Configuration public class ScheduleConfig {@Beanpublic SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {// Quartz參數(shù)配置Properties prop = new Properties();// Schedule調(diào)度器的實(shí)體名字prop.put("org.quartz.scheduler.instanceName", "HuskyScheduler");// 設(shè)置為AUTO時(shí)使用,默認(rèn)的實(shí)現(xiàn)org.quartz.scheduler.SimpleInstanceGenerator是基于主機(jī)名稱(chēng)和時(shí)間戳生成。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)行時(shí)用來(lái)存儲(chǔ)相關(guān)的信息// JDBCJobStore和JobStoreTX都使用關(guān)系數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)Schedule相關(guān)的信息。// JobStoreTX在每次執(zhí)行任務(wù)后都使用commit或者rollback來(lái)提交更改。prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");// 集群配置:如果有多個(gè)調(diào)度器實(shí)體的話則必須設(shè)置為trueprop.put("org.quartz.jobStore.isClustered", "true");// 集群配置:檢查集群下的其他調(diào)度器實(shí)體的時(shí)間間隔prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");// 設(shè)置一個(gè)頻度(毫秒),用于實(shí)例報(bào)告給集群中的其他實(shí)例prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");// 觸發(fā)器觸發(fā)失敗后再次觸犯的時(shí)間間隔prop.put("org.quartz.jobStore.misfireThreshold", "12000");// 數(shù)據(jù)庫(kù)表前綴prop.put("org.quartz.jobStore.tablePrefix", "qrtz_");// 從 LOCKS 表查詢(xún)一行并對(duì)這行記錄加鎖的 SQL 語(yǔ)句prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");// 定時(shí)器工廠配置SchedulerFactoryBean factory = new SchedulerFactoryBean();factory.setDataSource(dataSource);factory.setQuartzProperties(prop);factory.setSchedulerName("HuskyScheduler");factory.setStartupDelay(30);factory.setApplicationContextSchedulerContextKey("applicationContextKey");// 可選,QuartzScheduler 啟動(dòng)時(shí)更新己存在的Jobfactory.setOverwriteExistingJobs(true);// 設(shè)置自動(dòng)啟動(dòng),默認(rèn)為truefactory.setAutoStartup(true);return factory;} }3、定時(shí)器管理工具
import com.quart.job.entity.ScheduleJobBean; import org.quartz.*; /*** 定時(shí)器工具類(lèi)*/ 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) ;}/*** 定時(shí)器 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)建定時(shí)器*/public static void createJob (Scheduler scheduler, ScheduleJobBean scheduleJob){try {// 構(gòu)建定時(shí)器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) ;// 如果該定時(shí)器處于暫停狀態(tài)if (scheduleJob.getStatus() == 1){pauseJob(scheduler,scheduleJob.getJobId()) ;}} catch (SchedulerException e){throw new RuntimeException("createJob Fail",e) ;}}/*** 更新定時(shí)任務(wù)*/public static void updateJob(Scheduler scheduler, ScheduleJobBean scheduleJob) {try {// 構(gòu)建定時(shí)器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);// 如果該定時(shí)器處于暫停狀態(tài)if(scheduleJob.getStatus() == 1){pauseJob(scheduler, scheduleJob.getJobId());}} catch (SchedulerException e) {throw new RuntimeException("updateJob Fail",e) ;}}/*** 停止定時(shí)器*/public static void pauseJob (Scheduler scheduler,Long jobId){try {scheduler.pauseJob(getJobKey(jobId));} catch (SchedulerException e){throw new RuntimeException("pauseJob Fail",e) ;}}/*** 恢復(fù)定時(shí)器*/public static void resumeJob (Scheduler scheduler,Long jobId){try {scheduler.resumeJob(getJobKey(jobId));} catch (SchedulerException e){throw new RuntimeException("resumeJob Fail",e) ;}}/*** 刪除定時(shí)器*/public static void deleteJob (Scheduler scheduler,Long jobId){try {scheduler.deleteJob(getJobKey(jobId));} catch (SchedulerException e){throw new RuntimeException("deleteJob Fail",e) ;}}/*** 執(zhí)行定時(shí)器*/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、定時(shí)器執(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; /*** 定時(shí)器執(zhí)行日志記錄*/ public class TaskJobLog extends QuartzJobBean {private static final Logger LOG = LoggerFactory.getLogger(TaskJobLog.class) ;@Overrideprotected void executeInternal(JobExecutionContext context) {ScheduleJobBean jobBean = (ScheduleJobBean)context.getMergedJobDataMap().get(ScheduleJobBean.JOB_PARAM_KEY) ;ScheduleJobLogService scheduleJobLogService = (ScheduleJobLogService)SpringContextUtil.getBean("scheduleJobLogService") ;// 定時(shí)器日志記錄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í)行定時(shí)器的 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("定時(shí)器 === >> "+jobBean.getJobId()+"執(zhí)行成功,耗時(shí) === >> " + executeTime);} catch (Exception e){// 異常信息long executeTime = System.currentTimeMillis() - beginTime;logBean.setTimes((int)executeTime);logBean.setStatus(1);logBean.setError(e.getMessage());} finally {scheduleJobLogService.insert(logBean) ;}} }三、定時(shí)器服務(wù)封裝
1、定時(shí)器初始化
@Service public class ScheduleJobServiceImpl implements ScheduleJobService {@Resourceprivate Scheduler scheduler ;@Resourceprivate ScheduleJobMapper scheduleJobMapper ;/*** 定時(shí)器初始化*/@PostConstructpublic 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、添加定時(shí)器
@Override @Transactional(rollbackFor = Exception.class) public int insert(ScheduleJobBean record) {ScheduleUtil.createJob(scheduler,record);return scheduleJobMapper.insert(record); }3、立即執(zhí)行一次定時(shí)器
@Override @Transactional(rollbackFor = Exception.class) public void run(Long jobId) {ScheduleJobBean scheduleJobBean = scheduleJobMapper.selectByPrimaryKey(jobId) ;ScheduleUtil.run(scheduler,scheduleJobBean); }4、更新定時(shí)器
@Override @Transactional(rollbackFor = Exception.class) public int updateByPrimaryKeySelective(ScheduleJobBean record) {ScheduleUtil.updateJob(scheduler,record);return scheduleJobMapper.updateByPrimaryKeySelective(record); }5、停止定時(shí)器
@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ù)定時(shí)器
@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、刪除定時(shí)器
@Override @Transactional(rollbackFor = Exception.class) public void delete(Long jobId) {ScheduleUtil.deleteJob(scheduler, jobId);scheduleJobMapper.deleteByPrimaryKey(jobId) ; }四、配置一個(gè)測(cè)試的定時(shí)器
1、定時(shí)接口封裝
public interface TaskService {void run(String params); }2、測(cè)試定時(shí)器
@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") ;@Overridepublic void run(String params) {LOG.info("Params === >> " + params);LOG.info("當(dāng)前時(shí)間::::"+format.format(new Date()));} }五、源代碼
GitHub:知了一笑 https://github.com/cicadasmile/middle-ware-parent
總結(jié)
以上是生活随笔為你收集整理的SpringBoot2.0 整合 QuartJob ,实现定时器实时管理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Hibernate 中集合对象的抓取策略
- 下一篇: AutoEncoder概念【常用】