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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。