轉自https://blog.csdn.net/shasiqq/article/details/80421479
https://blog.csdn.net/li614814/article/details/80543515
我只貼代碼:
1.配置pom.xml
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency> <dependency><!-- 該依賴必加,里面有sping對schedule的支持 --> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency>
2.先寫一個監聽器保證項目啟動的時候會調用到,我們的定時任務,代碼如下
import org.quartz.SchedulerException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.ContextRefreshedEvent; import com.fjaidata.timer.MyScheduler; @Configuration public class SchedulerListener implements ApplicationListener<ContextRefreshedEvent>{ @Autowired public MyScheduler myScheduler; @Override public void onApplicationEvent(ContextRefreshedEvent event) { try { myScheduler.scheduleJobs(); } catch (SchedulerException e) { e.printStackTrace(); } } }
3.寫我們自己的定時器,用來觸發我們的任務
import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.TriggerBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import org.springframework.stereotype.Component; import com.fjaidata.job.AiArticleJob; import com.fjaidata.job.SealedBiddingJob; @Component public class MyScheduler { @Autowired SchedulerFactoryBean schedulerFactoryBean; static Scheduler scheduler; public void scheduleJobs() throws SchedulerException { scheduler = schedulerFactoryBean.getScheduler(); startJob1(); startJob2(); } public static void startJob1() throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(AiArticleJob.class).withIdentity("job1", "group1").build(); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0 0 8 * * ?"); CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") .withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail, cronTrigger); } public static void startJob2() throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(SealedBiddingJob.class).withIdentity("job2", "group1").build(); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0 0 8 ? * MON,FRI"); CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "group1") .withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail, cronTrigger); } }
4.定時器
@Configuration public class SealedBiddingJob implements Job{ @Autowired private SealedBiddingMapper biddingMapper; @Override public void execute(JobExecutionContext context) throws JobExecutionException {}
}
這是我們會發現總是報空指針的問題
原因:在quartz框架中,Job 是通過反射出來的實例,不受spring的管理。Scheduler現在交給Spring生成,在Spirng-context-support jar包下org.springframework.scheduling.quartz包中有個SpringBeanJobFactory的類,job實例通過該類的createJobInstance方法創建。根據Scheduler context、job data map and trigger data map填充其屬性。但是創建的job實例並沒被spring管理,這就需要我們自定義一個類將創建的job添加到applicationContext中,該類需要繼承SpringBeanJobFactory,並實現ApplicationContextAware接口。
ApplicationContextAware接口的作用:Spring容器會檢測容器中的所有Bean,如果發現某個Bean實現了ApplicationContextAware接口,Spring容器會在創建該Bean之后,自動調用該Bean的setApplicationContextAware()方法,調用該方法時,會將容器本身作為參數傳給該方法——該方法中的實現部分將Spring傳入的參數(容器本身)賦給該類對象的applicationContext實例變量,因此接下來可以通過該applicationContext實例變量來訪問容器本身。
import org.quartz.spi.TriggerFiredBundle; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.scheduling.quartz.SpringBeanJobFactory; public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware { private transient AutowireCapableBeanFactory autowireCapablebeanFactory; @Override public void setApplicationContext(final ApplicationContext context) { autowireCapablebeanFactory = context.getAutowireCapableBeanFactory(); } @Override protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { final Object job = super.createJobInstance(bundle); autowireCapablebeanFactory.autowireBean(job); return job; } }
@Configuration public class SchedulerConfig { @Bean public JobFactory jobFactory(ApplicationContext applicationContext) { AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory(); jobFactory.setApplicationContext(applicationContext); return jobFactory; } @Bean public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) throws Exception { SchedulerFactoryBean factory = new SchedulerFactoryBean(); factory.setOverwriteExistingJobs(true); factory.setJobFactory(jobFactory); factory.afterPropertiesSet(); return factory; } }