Spring Boot 2 整合 QuartJob 实现定时器实时管理功能
一、QuartJob简介
1、一句话描述
Quartz是一个完全由java编写的开源作业调度框架,形式简易,功能强大。
2、核心API
(1)、Scheduler
代表一个Quartz的独立运行容器,Scheduler将Trigger绑定到特定JobDetail,这样当Trigger触发时,对应的Job就会被调度。
(2)、Trigger
描述Job执行的时间触发规则。主要有SimpleTrigger和CronTrigger两个子类,通过一个TriggerKey唯一标识。
(3)、Job
定义一个任务,规定了任务是执行时的行为。JobExecutionContext提供了调度器的上下文信息,Job的数据可从JobDataMap中获取。
(4)、JobDetail
Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类。描述Job的实现类及其它相关的静态信息,如Job名字、描述等。
二、与SpringBoot2.0整合
1、项目结构
版本描述
spring-boot:2.1.3.RELEASE
quart-job:2.3.0
2、定时器配置
importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.scheduling.quartz.SchedulerFactoryBean; importjavax.sql.DataSource; importjava.util.Properties; @Configuration publicclassScheduleConfig{ @Bean publicSchedulerFactoryBeanschedulerFactoryBean(DataSourcedataSource){ //Quartz参数配置 Propertiesprop=newProperties(); //Schedule调度器的实体名字 prop.put("org.quartz.scheduler.instanceName","HuskyScheduler"); //设置为AUTO时使用,默认的实现org.quartz.scheduler.SimpleInstanceGenerator是基于主机名称和时间戳生成。 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在运行时用来存储相关的信息 //JDBCJobStore和JobStoreTX都使用关系数据库来存储Schedule相关的信息。 //JobStoreTX在每次执行任务后都使用commit或者rollback来提交更改。 prop.put("org.quartz.jobStore.class","org.quartz.impl.jdbcjobstore.JobStoreTX"); //集群配置:如果有多个调度器实体的话则必须设置为true prop.put("org.quartz.jobStore.isClustered","true"); //集群配置:检查集群下的其他调度器实体的时间间隔 prop.put("org.quartz.jobStore.clusterCheckinInterval","15000"); //设置一个频度(毫秒),用于实例报告给集群中的其他实例 prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime","1"); //触发器触发失败后再次触犯的时间间隔 prop.put("org.quartz.jobStore.misfireThreshold","12000"); //数据库表前缀 prop.put("org.quartz.jobStore.tablePrefix","qrtz_"); //从LOCKS表查询一行并对这行记录加锁的SQL语句 prop.put("org.quartz.jobStore.selectWithLockSQL","SELECT*FROM{0}LOCKSUPDLOCKWHERELOCK_NAME=?"); //定时器工厂配置 SchedulerFactoryBeanfactory=newSchedulerFactoryBean(); factory.setDataSource(dataSource); factory.setQuartzProperties(prop); factory.setSchedulerName("HuskyScheduler"); factory.setStartupDelay(30); factory.setApplicationContextSchedulerContextKey("applicationContextKey"); //可选,QuartzScheduler启动时更新己存在的Job factory.setOverwriteExistingJobs(true); //设置自动启动,默认为true factory.setAutoStartup(true); returnfactory; } }
3、定时器管理工具
importcom.quart.job.entity.ScheduleJobBean; importorg.quartz.*; /** *定时器工具类 */ publicclassScheduleUtil{ privateScheduleUtil(){} privatestaticfinalStringSCHEDULE_NAME="HUSKY_"; /** *触发器KEY */ publicstaticTriggerKeygetTriggerKey(LongjobId){ returnTriggerKey.triggerKey(SCHEDULE_NAME+jobId); } /** *定时器Key */ publicstaticJobKeygetJobKey(LongjobId){ returnJobKey.jobKey(SCHEDULE_NAME+jobId); } /** *表达式触发器 */ publicstaticCronTriggergetCronTrigger(Schedulerscheduler,LongjobId){ try{ return(CronTrigger)scheduler.getTrigger(getTriggerKey(jobId)); }catch(SchedulerExceptione){ thrownewRuntimeException("getCronTriggerFail",e); } } /** *创建定时器 */ publicstaticvoidcreateJob(Schedulerscheduler,ScheduleJobBeanscheduleJob){ try{ //构建定时器 JobDetailjobDetail=JobBuilder.newJob(TaskJobLog.class).withIdentity(getJobKey(scheduleJob.getJobId())).build(); CronScheduleBuilderscheduleBuilder=CronScheduleBuilder .cronSchedule(scheduleJob.getCronExpression()) .withMisfireHandlingInstructionDoNothing(); CronTriggertrigger=TriggerBuilder.newTrigger() .withIdentity(getTriggerKey(scheduleJob.getJobId())) .withSchedule(scheduleBuilder).build(); jobDetail.getJobDataMap().put(ScheduleJobBean.JOB_PARAM_KEY,scheduleJob); scheduler.scheduleJob(jobDetail,trigger); //如果该定时器处于暂停状态 if(scheduleJob.getStatus()==1){ pauseJob(scheduler,scheduleJob.getJobId()); } }catch(SchedulerExceptione){ thrownewRuntimeException("createJobFail",e); } } /** *更新定时任务 */ publicstaticvoidupdateJob(Schedulerscheduler,ScheduleJobBeanscheduleJob){ try{ //构建定时器 TriggerKeytriggerKey=getTriggerKey(scheduleJob.getJobId()); CronScheduleBuilderscheduleBuilder=CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()) .withMisfireHandlingInstructionDoNothing(); CronTriggertrigger=getCronTrigger(scheduler,scheduleJob.getJobId()); trigger=trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); trigger.getJobDataMap().put(ScheduleJobBean.JOB_PARAM_KEY,scheduleJob); scheduler.rescheduleJob(triggerKey,trigger); //如果该定时器处于暂停状态 if(scheduleJob.getStatus()==1){ pauseJob(scheduler,scheduleJob.getJobId()); } }catch(SchedulerExceptione){ thrownewRuntimeException("updateJobFail",e); } } /** *停止定时器 */ publicstaticvoidpauseJob(Schedulerscheduler,LongjobId){ try{ scheduler.pauseJob(getJobKey(jobId)); }catch(SchedulerExceptione){ thrownewRuntimeException("pauseJobFail",e); } } /** *恢复定时器 */ publicstaticvoidresumeJob(Schedulerscheduler,LongjobId){ try{ scheduler.resumeJob(getJobKey(jobId)); }catch(SchedulerExceptione){ thrownewRuntimeException("resumeJobFail",e); } } /** *删除定时器 */ publicstaticvoiddeleteJob(Schedulerscheduler,LongjobId){ try{ scheduler.deleteJob(getJobKey(jobId)); }catch(SchedulerExceptione){ thrownewRuntimeException("deleteJobFail",e); } } /** *执行定时器 */ publicstaticvoidrun(Schedulerscheduler,ScheduleJobBeanscheduleJob){ try{ JobDataMapdataMap=newJobDataMap(); dataMap.put(ScheduleJobBean.JOB_PARAM_KEY,scheduleJob); scheduler.triggerJob(getJobKey(scheduleJob.getJobId()),dataMap); }catch(SchedulerExceptione){ thrownewRuntimeException("runFail",e); } } }
4、定时器执行和日志
importcom.quart.job.entity.ScheduleJobBean; importcom.quart.job.entity.ScheduleJobLogBean; importcom.quart.job.service.ScheduleJobLogService; importorg.quartz.JobExecutionContext; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.scheduling.quartz.QuartzJobBean; importjava.lang.reflect.Method; importjava.util.Date; /** *定时器执行日志记录 */ publicclassTaskJobLogextendsQuartzJobBean{ privatestaticfinalLoggerLOG=LoggerFactory.getLogger(TaskJobLog.class); @Override protectedvoidexecuteInternal(JobExecutionContextcontext){ ScheduleJobBeanjobBean=(ScheduleJobBean)context.getMergedJobDataMap().get(ScheduleJobBean.JOB_PARAM_KEY); ScheduleJobLogServicescheduleJobLogService=(ScheduleJobLogService)SpringContextUtil.getBean("scheduleJobLogService"); //定时器日志记录 ScheduleJobLogBeanlogBean=newScheduleJobLogBean(); logBean.setJobId(jobBean.getJobId()); logBean.setBeanName(jobBean.getBeanName()); logBean.setParams(jobBean.getParams()); logBean.setCreateTime(newDate()); longbeginTime=System.currentTimeMillis(); try{ //加载并执行定时器的run方法 Objecttarget=SpringContextUtil.getBean(jobBean.getBeanName()); Methodmethod=target.getClass().getDeclaredMethod("run",String.class); method.invoke(target,jobBean.getParams()); longexecuteTime=System.currentTimeMillis()-beginTime; logBean.setTimes((int)executeTime); logBean.setStatus(0); LOG.info("定时器===>>"+jobBean.getJobId()+"执行成功,耗时===>>"+executeTime); }catch(Exceptione){ //异常信息 longexecuteTime=System.currentTimeMillis()-beginTime; logBean.setTimes((int)executeTime); logBean.setStatus(1); logBean.setError(e.getMessage()); }finally{ scheduleJobLogService.insert(logBean); } } }
三、定时器服务封装
1、定时器初始化
@Service publicclassScheduleJobServiceImplimplementsScheduleJobService{ @Resource privateSchedulerscheduler; @Resource privateScheduleJobMapperscheduleJobMapper; /** *定时器初始化 */ @PostConstruct publicvoidinit(){ ScheduleJobExampleexample=newScheduleJobExample(); ListscheduleJobBeanList=scheduleJobMapper.selectByExample(example); for(ScheduleJobBeanscheduleJobBean:scheduleJobBeanList){ CronTriggercronTrigger=ScheduleUtil.getCronTrigger(scheduler,scheduleJobBean.getJobId()); if(cronTrigger==null){ ScheduleUtil.createJob(scheduler,scheduleJobBean); }else{ ScheduleUtil.updateJob(scheduler,scheduleJobBean); } } } }
2、添加定时器
@Override @Transactional(rollbackFor=Exception.class) publicintinsert(ScheduleJobBeanrecord){ ScheduleUtil.createJob(scheduler,record); returnscheduleJobMapper.insert(record); }
3、立即执行一次定时器
@Override @Transactional(rollbackFor=Exception.class) publicvoidrun(LongjobId){ ScheduleJobBeanscheduleJobBean=scheduleJobMapper.selectByPrimaryKey(jobId); ScheduleUtil.run(scheduler,scheduleJobBean); }
4、更新定时器
@Override @Transactional(rollbackFor=Exception.class) publicintupdateByPrimaryKeySelective(ScheduleJobBeanrecord){ ScheduleUtil.updateJob(scheduler,record); returnscheduleJobMapper.updateByPrimaryKeySelective(record); }
5、停止定时器
@Override @Transactional(rollbackFor=Exception.class) publicvoidpauseJob(LongjobId){ ScheduleJobBeanscheduleJobBean=scheduleJobMapper.selectByPrimaryKey(jobId); ScheduleUtil.pauseJob(scheduler,jobId); scheduleJobBean.setStatus(1); scheduleJobMapper.updateByPrimaryKeySelective(scheduleJobBean); }
6、恢复定时器
@Override @Transactional(rollbackFor=Exception.class) publicvoidresumeJob(LongjobId){ ScheduleJobBeanscheduleJobBean=scheduleJobMapper.selectByPrimaryKey(jobId); ScheduleUtil.resumeJob(scheduler,jobId); scheduleJobBean.setStatus(0); scheduleJobMapper.updateByPrimaryKeySelective(scheduleJobBean); }
7、删除定时器
@Override @Transactional(rollbackFor=Exception.class) publicvoiddelete(LongjobId){ ScheduleUtil.deleteJob(scheduler,jobId); scheduleJobMapper.deleteByPrimaryKey(jobId); }
四、配置一个测试的定时器
1、定时接口封装
publicinterfaceTaskService{ voidrun(Stringparams); }
2、测试定时器
@Component("getTimeTask") publicclassGetTimeTaskimplementsTaskService{ privatestaticfinalLoggerLOG=LoggerFactory.getLogger(GetTimeTask.class.getName()); privatestaticfinalSimpleDateFormatformat= newSimpleDateFormat("yyyy-MM-ddHH:mm:ss"); @Override publicvoidrun(Stringparams){ LOG.info("Params===>>"+params); LOG.info("当前时间::::"+format.format(newDate())); } }
五、源代码
GitHub:知了一笑
https://github.com/cicadasmile/middle-ware-parent
总结
以上所述是小编给大家介绍的SpringBoot2整合QuartJob实现定时器实时管理功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。