在Spring/SpringBoot下实现定时任务非常简单。我们只需要通过@EnableScheduling开启对定时任务的支持,然后使用@Scheduled注解制定定时任务,这样的实现就解决了我们对定时任务的大部分需求。但是在很多情况下,上述方法实现的定时任务是硬编码在代码中的,我们只需要修改代码就可以修改定时任务。很多时候,我们需要从外部设置定时任务执行的时间和方式。所以在这篇文章中,我们重点讲解如何动态配置定时任务。和Spring对异步任务的支持一样,通过@EnableAsync注解开启异步支持,然后通过@Async注解指定异步方法。真正的异步任务执行器是TaskExecutor接口,它的实现是ThreadPoolTask??Executor。同样,Spring对计划任务的支持也是通过@EnableScheduling开启计划任务,然后使用@Scheduled注解制定计划任务。真正的任务执行者是TaskScheduler接口,它的实现是ThreadPoolTask??Scheduler。TaskScheduler接口主要有3个方法:publicinterfaceTaskScheduler{//指定开始定时任务的时间ScheduledFuture>schedule(Runnabletask,Triggertrigger);ScheduledFuture>schedule(Runnabletask,DatestartTime);//指定启动计划任务的频率ScheduledFuture>scheduleAtFixedRate(Runnabletask,DatestartTime,longperiod);ScheduledFuture>scheduleAtFixedRate(Runnabletask,longperiod);//指定延迟启动定时任务ScheduledFuture>scheduleWithFixedDelay(Runnabletask,DatestartTime,longdelay);ScheduledFuture>scheduleWithFixedDelay(Runnabletask,longdelay);}该方法的返回值为ScheduledFuture接口,可用于取消任务或检查任务是否完成。实际要执行的任务是Runnable的实现类。那么我们就可以通过TaskScheduler实现动态定时任务。SpringBoot为我们提供了TaskSchedulingAutoConfiguration自动配置来自动注册TaskScheduler的Bean。所以我们不需要配置可以直接注入TaskScheduler的bean。SpringBoo也提供了TaskSchedulingProperties来配置TaskScheduler,我们可以通过spring.task.scheduling的属性来配置。新建一个demo项目:构建一个需要定时启动的任务publicclassRunnableTaskimplementsRunnable{privateStringtaskName;私人工作服务工作服务;publicRunnableTask(StringtaskName,WorkingServiceworkingService){this.taskName=taskName;this.workingService=workingService;}@Overridepublicvoidrun(){workingService.work(taskName);}}这里,为了还原真实,我们一般在任务中调用Spring容器中的其他类来操作。这里我们引入一个WorkingService来实际执行任务。SimpleWorkingService@Service@Slf4jpublicclassWorkingService{publicvoidwork(StringtaskName){log.info("当前任务:"+taskName+"在线程上运行"+Thread.currentThread().getName()+"");}}使用TaskScheduler的bean启动定时任务@ServicepublicclassSchedulingService{privatefinalTaskSchedulertaskScheduler;//可以直接注入TaskScheduler的BeanprivatefinalWorkingServiceworkingService;//构造函数注入,避免@AutowiredpublicSc??hedulingService(TaskSchedulertaskScheduler,WorkingServiceworkingService){this.taskScheduler=taskScheduler;this.workingService=workingService;}publicvoidschedule(StringtaskName,StringcronExpression){//RunnableTask不是Bean,所以不能直接注入workingService,它的构造函数直接传入RunnableTasktask=newRunnableTask(taskName,workingService);CronTriggercronTrigger=newCronTrigger(cronExpression);//api接受要执行的实际任务,以及cron表达式taskScheduler.schedule(task,cronTrigger);}公共无效时间表leAtFixedRate(StringtaskName,longperiod){RunnableTasktask=newRunnableTask(taskName,workingService);//api接受实际执行的任务,以及间隔时间taskScheduler.scheduleAtFixedRate(task,period);}publicvoidscheduleWithFixedDelay(StringtaskName,longdelay){RunnableTasktask=newRunnableTask(taskName,workingService);//api接受实际要执行的任务,以及延迟时间taskScheduler.scheduleWithFixedDelay(task,delay);}}在启动类设置动态配置@SpringBootApplication@EnableSchedulingpublicclassDynamicTaskSchedulerApplication{publicstaticvoidmain(String[]args){SpringApplication.run(DynamicTaskSchedulerApplication.class,args);}@BeanCommandLineRunnercommandLineRunner(SchedulingServiceschedulingService,WorkingServiceworkingService){returnargs->{schedulingService.schedule("指定时间任务","50****THU");schedulingService.scheduleAtFixedRate("指定频率任务",1000);调度服务.scheduleWithFixedDelay("指定延时任务",1000);};}}application.propertiesspring.task.scheduling.pool.size=3spring.task.scheduling.thread-name-prefix=wisely-starter-validation的配置(这里已经添加书卡,请到今日头条客户端查看看看吧)文章来自:热爱科学的Wesley,如需转载本文,请联系热爱科学的Wesley今天头条号
