spring boot 集成 spring-boot-starter-quartz 集群版配置
1、引入依赖
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-quartz</artifactId> 4 </dependency>
2、添加quartz配置文件
1 org.quartz.scheduler.instanceName = schedulerFactoryBean 2 org.quartz.scheduler.instanceId = AUTO 3 org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate 4 org.quartz.jobStore.tablePrefix = QRTZ_ 5 org.quartz.jobStore.useProperties = false 6 org.quartz.jobStore.isClustered=true 7 org.quartz.jobStore.clusterCheckinInterval=30000 8 org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool 9 org.quartz.threadPool.threadCount = 10 10 org.quartz.threadPool.threadPriority = 5
3、quartz 使用
- 开启配置
1 package cn.xs.qishi.cas.quartz; 2 3 import cn.xs.ambi.jds.dd.RoutingDatasource; 4 import org.quartz.spi.JobFactory; 5 import org.quartz.spi.TriggerFiredBundle; 6 import org.springframework.beans.factory.annotation.Autowire; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 9 import org.springframework.context.ApplicationContext; 10 import org.springframework.context.ApplicationContextAware; 11 import org.springframework.context.annotation.Bean; 12 import org.springframework.context.annotation.Configuration; 13 import org.springframework.core.io.ClassPathResource; 14 import org.springframework.scheduling.quartz.SchedulerFactoryBean; 15 import org.springframework.scheduling.quartz.SpringBeanJobFactory; 16 17 /** 18 * @author liuxn 19 * @date 2022/6/28 20 */ 21 @Configuration 22 public class SchedulerConfig { 23 24 @Autowired 25 private RoutingDatasource datasource; 26 27 public static class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements 28 ApplicationContextAware { 29 30 private transient AutowireCapableBeanFactory beanFactory; 31 32 @Override 33 public void setApplicationContext(final ApplicationContext context) { 34 beanFactory = context.getAutowireCapableBeanFactory(); 35 } 36 37 @Override 38 protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { 39 final Object job = super.createJobInstance(bundle); 40 beanFactory.autowireBean(job); 41 return job; 42 } 43 } 44 45 46 @Bean 47 public JobFactory jobFactory() { 48 AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory(); 49 return jobFactory; 50 } 51 52 53 @Bean(destroyMethod = "destroy", autowire = Autowire.NO) 54 public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) throws Exception { 55 SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); 56 //将spring管理job自定义工厂交由调度器维护 57 schedulerFactoryBean.setJobFactory(jobFactory); 58 //设置覆盖已存在的任务 59 schedulerFactoryBean.setOverwriteExistingJobs(true); 60 //设置数据源,使用与项目统一数据源 61 schedulerFactoryBean.setDataSource(datasource); 62 //设置配置文件位置 63 schedulerFactoryBean.setConfigLocation(new ClassPathResource("/quartz.properties")); 64 return schedulerFactoryBean; 65 } 66 }
备注:以上是业务和quartz使用同一个数据源若使用独立数据源则使用注解 @QuartzDataSource
2. 业务使用
1 package cn.xs.qishi.cas.quartz; 2 3 import cn.xs.ambi.bas.util.DateUtils; 4 import cn.xs.qishi.cas.constant.Constant; 5 import lombok.CustomLog; 6 import org.quartz.*; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.stereotype.Component; 9 10 import java.util.Date; 11 12 /** 13 * 定时任务调度器 14 * 15 * @author liuxn 16 * @date 2022/6/28 17 */ 18 @Component 19 @CustomLog 20 public class MonitorWoJobService { 21 22 @Autowired 23 private Scheduler scheduler; 24 25 //删除任务 26 public void deleteJob(JobDto job) throws SchedulerException { 27 JobKey jobKey = JobKey.jobKey(job.getJobNo(), job.getJobGroup()); 28 TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobNo(), job.getJobGroup()); 29 boolean exists = scheduler.checkExists(jobKey); 30 Trigger trigger = scheduler.getTrigger(triggerKey); 31 if (exists && trigger != null) { 32 // 停止触发器 33 scheduler.pauseTrigger(triggerKey); 34 // 移除触发器 35 scheduler.unscheduleJob(triggerKey); 36 // 删除任务 37 scheduler.deleteJob(jobKey); 38 } 39 log.info(">> 删除任务taskId:" + job.getJobId() + "taskNo:[" + job.getJobNo() + "]"); 40 } 41 42 //更新任务 43 public void updateJob(JobDto job) throws SchedulerException { 44 TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobNo(), job.getJobGroup()); 45 Date startAt = DateBuilder.evenHourDateBefore(job.getStart()); 46 SimpleTrigger trigger = (SimpleTrigger) scheduler.getTrigger(triggerKey); 47 TriggerBuilder<SimpleTrigger> triggerBuilder = trigger.getTriggerBuilder(); 48 SimpleScheduleBuilder newBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInMinutes(job.getInterval()).repeatForever(); 49 triggerBuilder.withIdentity(triggerKey).withSchedule(newBuilder); 50 triggerBuilder.startAt(startAt); 51 if (job.getEnd() != null) { 52 triggerBuilder.endAt(job.getEnd()); 53 } 54 trigger = triggerBuilder.build(); 55 scheduler.rescheduleJob(triggerKey, trigger); 56 log.info(">> 更新任务taskId:" + job.getJobId() + "taskNo:[" + job.getJobNo() + "],开始时间:[" + DateUtils.emptyFormat(startAt) + "],时间间隔:[" + job.getInterval() + "]分钟"); 57 } 58 59 //添加任务 60 public void addJob(JobDto job) throws SchedulerException { 61 JobDetail jobDetail = JobBuilder.newJob(MonitorWoJob.class).withIdentity(job.getJobNo(), job.getJobGroup()).storeDurably().build(); 62 Date startAt = DateBuilder.evenHourDateBefore(job.getStart() == null ? new Date() : job.getStart()); 63 JobDataMap jobDataMap = jobDetail.getJobDataMap(); 64 jobDataMap.put(Constant.Task.TASK_ID, job.getJobId()); 65 jobDataMap.put(Constant.Task.TASK_NO, job.getJobNo()); 66 Trigger trigger = TriggerBuilder 67 .newTrigger() 68 .withSchedule(SimpleScheduleBuilder.repeatMinutelyForever(job.getInterval())) 69 .usingJobData(jobDataMap).startAt(startAt) 70 .forJob(jobDetail.getKey()) 71 .build(); 72 boolean exists = scheduler.checkExists(jobDetail.getKey()); 73 if (exists) { 74 log.info(">> 移除任务"); 75 scheduler.pauseTrigger(trigger.getKey()); 76 scheduler.unscheduleJob(trigger.getKey()); 77 scheduler.deleteJob(jobDetail.getKey()); 78 } 79 scheduler.scheduleJob(jobDetail, trigger); 80 log.info(">> 任务调度器启动状态:" + scheduler.isStarted()); 81 if (!scheduler.isStarted()) { 82 scheduler.start(); 83 } 84 log.info(">> 新增任务taskId:[" + job.getJobId() + "],taskNo:[" + job.getJobNo() + "],开始时间:[" + DateUtils.emptyFormat(startAt) + "],时间间隔:[" + job.getInterval() + "]分钟"); 85 } 86 }
3.任务类
1 package cn.xs.qishi.cas.quartz; 2 3 import cn.xs.ambi.mgt.redis.RedisManager; 4 import cn.xs.qishi.cache.key.RedisPrefixOfCas; 5 import cn.xs.qishi.cas.constant.Constant; 6 import cn.xs.qishi.cas.service.impl.CasMonitorTaskServiceTx; 7 import cn.xs.qishi.entity.pojo.WoMonitorRule; 8 import cn.xs.qishi.entity.pojo.WoMonitorTask; 9 import com.alibaba.fastjson.JSON; 10 import lombok.CustomLog; 11 import org.quartz.*; 12 import org.springframework.beans.factory.annotation.Autowired; 13 import org.springframework.scheduling.quartz.QuartzJobBean; 14 import org.springframework.stereotype.Component; 15 16 import java.util.List; 17 18 /** 19 * 任务 20 * 21 * @author liuxn 22 * @date 2022/6/28 23 */ 24 @CustomLog 25 @Component 26 @DisallowConcurrentExecution 27 public class MonitorWoJob extends QuartzJobBean { 28 29 30 @Override 31 protected void executeInternal(JobExecutionContext context) throws JobExecutionException { 32 try { 33 JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); 34 log.info(">> 工单监控任务触发 " + JSON.toJSONString(jobDataMap)); 35 //todo 实现自己的业务 36 } catch (Exception e) { 37 log.error("工单监控计算job异常", e); 38 } 39 } 40 }
备注:@DisallowConcurrentExecution 注解使用保证了同一个任务只能在一台机器上触发 本demo是才是 SimpleScheduleBuilder 实现。 CronScheduleBuilder 详情见 官放文档 http://www.quartz-scheduler.org/documentation