在实际项目中经常会用到定时任务,且有些定时任务同时只能运行一个实例,下面介绍一下通过Spring boot + Quartz框架实现分布式定时任务。
1. 定时任务持久化到Mysql
2. 名称为JobA的定时任务每10秒执行一次@ScheduledJob(name = “JobA”, cronExp = “/10 * * * ?”)
3. @DisallowConcurrentExecution同一个定时任务同一时间只能有一个执行,如果定时任务执行时间超过10秒,丢弃或等待(未验证)
4. 此定时任务可以同时部署多个,支持Failover
5. Quartz相关SQL请参考https://github.com/465919283/demo/blob/master/sql/quartz.sql
<https://github.com/465919283/demo/blob/master/sql/quartz.sql>
quartz.properties org.quartz.scheduler.instanceName=spring-boot-quartz org
.quartz.scheduler.instanceId=AUTO org.quartz.threadPool.threadCount=5 org.quartz
.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore
.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz
.jobStore.useProperties=false org.quartz.jobStore.tablePrefix=QRTZ_ org.quartz
.jobStore.isClustered=true import org.quartz.spi.JobFactory; import
org.quartz.spi.TriggerFiredBundle;import
org.springframework.beans.factory.annotation.Autowired;import
org.springframework.beans.factory.config.AutowireCapableBeanFactory;import
org.springframework.beans.factory.config.PropertiesFactoryBean;import
org.springframework.context.ApplicationContext;import
org.springframework.context.ApplicationContextAware;import
org.springframework.context.annotation.Bean;import
org.springframework.context.annotation.Configuration;import
org.springframework.core.io.ClassPathResource;import
org.springframework.scheduling.quartz.SchedulerFactoryBean;import
org.springframework.scheduling.quartz.SpringBeanJobFactory;import
org.springframework.transaction.PlatformTransactionManager;@Configuration public
class QuartzConfig { public static final String QUARTZ_PROPERTIES_PATH =
"quartz.properties"; @Autowired private DataSource dataSource; @Autowired
private PlatformTransactionManager transactionManager; @Bean public JobFactory
jobFactory(ApplicationContext applicationContext) {
AutowiringSpringBeanJobFactory jobFactory =new
AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);return jobFactory; } @Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) throws
IOException { SchedulerFactoryBean factory =new SchedulerFactoryBean();
factory.setAutoStartup(true); factory.setJobFactory(jobFactory);
factory.setQuartzProperties(quartzProperties());//使用Spring boot中配置的数据源
factory.setDataSource(dataSource);
factory.setTransactionManager(transactionManager);return factory; } @Bean public
PropertiesquartzProperties() throws IOException { PropertiesFactoryBean
propertiesFactoryBean =new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new
ClassPathResource(QUARTZ_PROPERTIES_PATH));
propertiesFactoryBean.afterPropertiesSet();return
propertiesFactoryBean.getObject(); }public static class
AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
ApplicationContextAware { private transient AutowireCapableBeanFactory
beanFactory;@Override public void setApplicationContext(final
ApplicationContext context) { beanFactory =
context.getAutowireCapableBeanFactory(); }@Override protected Object
createJobInstance(final TriggerFiredBundle bundle) throws Exception { final
Object job =super.createJobInstance(bundle); beanFactory.autowireBean(job);
return job; } } } import java.lang.annotation.ElementType; import java.lang
.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java
.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy
.RUNTIME) public @interface ScheduledJob { String name(); String group() default
"DEFAULT_GROUP"; String cronExp(); } import org.quartz.CronScheduleBuilder;
import org.quartz.Job; import org.quartz.JobBuilder; import org.quartz.JobDetail
; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz
.SchedulerException; import org.quartz.Trigger; import org.quartz.TriggerBuilder
; import org.springframework.beans.BeansException; import org.springframework
.beans.factory.annotation.Autowired; import org.springframework.beans.factory
.config.BeanPostProcessor; import org.springframework.core.annotation
.AnnotationUtils; import org.springframework.stereotype.Component; @Component
public class ScheduleListener implements BeanPostProcessor { @Autowired private
Scheduler scheduler; @Override public Object
postProcessBeforeInitialization(Object bean, String beanName) throws
BeansException { return bean; } @Override public Object
postProcessAfterInitialization(Object bean, String beanName) throws
BeansException { ScheduledJob scheduledJob = AnnotationUtils.findAnnotation(bean
.getClass(), ScheduledJob.class); if (scheduledJob != null && bean instanceof
Job) { JobKey jobKey = new JobKey(scheduledJob.name(), scheduledJob.group());
JobDetail jobDetail = JobBuilder.newJob(((Job) bean).getClass()) .withIdentity
(jobKey).build(); Trigger trigger = TriggerBuilder.newTrigger() .withIdentity
(scheduledJob.name() + "Trigger", scheduledJob.group()) .forJob(jobDetail)
.withSchedule(CronScheduleBuilder.cronSchedule(scheduledJob.cronExp())) .build()
; try { if (!scheduler.checkExists(jobKey)) { scheduler.scheduleJob(jobDetail,
trigger); } } catch (SchedulerException e) { e.printStackTrace(); } } return
bean; } } import org.quartz.DisallowConcurrentExecution; import org.quartz.Job;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component; import
com.primer.demo.task.ScheduledJob;@Component @ScheduledJob(name = "JobA",
cronExp ="*/10 * * * * ?") @DisallowConcurrentExecution public class JobA
implements Job { @Override public void execute(JobExecutionContext context)
throws JobExecutionException { // TODO Auto-generated method stub
System.out.println("JobA................"); } }
完整代码请参考https://github.com/465919283/demo <https://github.com/465919283/demo>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信