產(chǎn)生這個需求的主要原因是寫了個簡單的爬取網(wǎng)易新聞的方法,但是總不能一直自己手動執(zhí)行吧,于是了解到了定時任務(wù)以及Quartz這個強大的框架,能夠設(shè)定執(zhí)行時間間隔和和何時停止等等??傊蚣芫褪欠浅5膬?yōu)秀。
本文主要介紹使用Spring Boot項目集成Quartz的過程及遇到的一些問題。
第一,依賴的兩個重要包。
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
其中,spring-context-support的作用為,quartz在運行任務(wù)時,是在spring容器里面吧,會用到其中的一些bean也就是類的實例吧,這個包就對這個需求實現(xiàn)了支持。
第二,以我自身需求為例,我想要定時執(zhí)行的任務(wù)是crawlBasicNewsInfo()這個方法,具體方法內(nèi)容就不給出了。這個任務(wù)方法的類實現(xiàn)Job類,并覆寫execute方法,如下代碼所示:
public class CrawlNewsJob implements Job {
@Autowired
private NewsRepository newsRepository;
@Autowired
private NewsmoduleRepository newsmoduleRepository;
private static Logger logger = Logger.getLogger(CrawlNewsJob.class);
@Override
public void execute(JobExecutionContext context){
crawlBasicNewsInfo();
}
第三,實現(xiàn)對job實例注入spring容器里面的一些bean的任務(wù),首先是覆寫框架創(chuàng)建JobInstance的方式,,定制我們自己的SpringJobFactory。不這么做的話,肯定會空指針了。
@Component
public class SpringJobFactory extends AdaptableJobFactory{
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception{
//調(diào)用父類獲取jobinstance
Object jobinstance = super.createJobInstance(bundle);
//此處給job實例注入spring容器中的bean
capableBeanFactory.autowireBean(jobinstance);
return jobinstance;
}
}
接著通過@Configuration、@Bean等注解進(jìn)行配置,這里就是Spring Boot的方便之處了,不需要xml去配置了。值得注意的是,對于注入的Schduler,必須要加入@Primary確保注入的是我們這個Bean,而不是框架中的,不加會出現(xiàn)Field scheduler in RecommenderApplication required a single bean, but 2 were found報錯。
@Configuration
public class QuartzConfig {
@Autowired
private SpringJobFactory springJobFactory;
@Bean(name = "SchedulerFactoryBean")
public SchedulerFactoryBean schedulerFactoryBean(){
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setJobFactory(springJobFactory);
return schedulerFactoryBean;
}
@Bean(name = "Scheduler")
@Primary
public Scheduler scheduler(){
return schedulerFactoryBean().getScheduler();
}
}
第四,實現(xiàn)了上述功能就可以實現(xiàn)定時任務(wù)了,但是如果現(xiàn)在需要項目啟動時就一直運行怎么辦?項目啟動時,需要跟Spring Boot一起運行的話,Spring Boot提供了兩種自啟動方式,一個是CommandLineRunner,一個是ApplicationRunner兩個接口,實現(xiàn)它的run方法,把你的定時任務(wù)放在其中就好啦。比如我的下面代碼所示。
@SpringBootApplication
public class RecommenderApplication implements ApplicationRunner{
private static Logger logger = Logger.getLogger(CrawlNewsJob.class);
@Autowired
private Scheduler scheduler;
public static void main(String[] args) throws SchedulerException,FileLockInterruptionException {
SpringApplication.run(RecommenderApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception{
try {
//Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
System.out.println("Quartz Start !");
//具體任務(wù)
JobDetail job = JobBuilder.newJob(CrawlNewsJob.class).withIdentity("job1","group1").build();
//觸發(fā)器
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInMinutes(60).repeatForever();
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1","group1").startNow().withSchedule(simpleScheduleBuilder).build();
scheduler.scheduleJob(job,trigger);
//睡眠
TimeUnit.MINUTES.sleep(360);
scheduler.shutdown();
System.out.println("scheduler shutdown ! ");
}catch(Exception e){e.printStackTrace();}
}
}
實現(xiàn)Spring Boot集成Quartz并使得項目啟動時執(zhí)行某些定時任務(wù),大致就是上面這些內(nèi)容了。開始你的表演吧。
原文:http://netrookie.cn/Spring-Boot%E9%9B%86%E6%88%90Quartz%E5%AE%9E%E7%8E%B0%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1/
公眾號:netrookie