11

Spring/Spring Boot下如何动态配置计划任务

 1 year ago
source link: https://www.51cto.com/article/721460.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Spring/Spring Boot下如何动态配置计划任务

作者:爱科学的卫斯理 2022-10-27 17:59:07
方法的返回值都是ScheduledFuture 接口,可以使用它来取消任务或者检查任务是否完成。而实际要执行的任务是Runnable的实现类。

在Spring/Spring Boot下实现计划任务是很简单的,我们只需通过@EnableScheduling 开启计划任务的支持,然后通过@Scheduled 注解来制定计划任务,这样的实现解决了我们对计划任务的绝大部分需求。

但在很多时候,通过上述方式实现的计划任务是在代码里写死的,我们需要修改计划任务只能通过修改代码的方式实现。很多时候,我们需要从外部来设置计划任务执行的时间和方式。所以在本文中,我们着重讲解一下如何动态地配置计划任务。

和Spring对异步任务的支持一样,通过@EnableAsync 注解开启异步的支持,然后通过@Async 注解来指定异步的方法,而真正的异步任务的执行者是TaskExecutor接口 ,它的实现是ThreadPoolTaskExecutor。

同样,Spring对计划任务的支持也是通过@EnableScheduling 开启计划任务的支持,然后通过@Scheduled 注解来制定计划任务,而真正的任务执行者是TaskScheduler 接口,它的实现是ThreadPoolTaskScheduler 。

TaskScheduler的接口有三类主要方法:

public interface TaskScheduler {
  
  //指定时间启动计划任务
   ScheduledFuture<?> schedule(Runnable task, Trigger trigger);
  ScheduledFuture<?> schedule(Runnable task, Date startTime);

  //指定频率启动计划任务
   ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period);
   ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period);
 
  //指定延迟启动计划任务
   ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
   ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay);
}

方法的返回值都是ScheduledFuture 接口,可以使用它来取消任务或者检查任务是否完成。而实际要执行的任务是Runnable的实现类。

那我们可以通过TaskScheduler来实现动态的计划任务的实现。Spring Boot为我们提供了TaskSchedulingAutoConfiguration自动配置来自动注册TaskScheduler 的Bean。所以我们无需配置可直接注入TaskScheduler的Bean即可使用。

e607e3570a6fd4a0392125e78297f696bc2d75.png

Spring Boo同样提供了TaskSchedulingProperties来TaskScheduler 进行配置,我们可以通过:spring.task.scheduling的属性进行配置。

新建一个演示项目:

d51e1c778069d1daae9079fba75588db4deb8d.png
  • 构建需要定时启动的任务
public class RunnableTask implements Runnable{
    private String taskName;
    private WorkingService workingService;
    
    public RunnableTask(String taskName, WorkingService workingService){
        this.taskName = taskName;
        this.workingService = workingService;
    }
    
    @Override
    public void run(){
        workingService.work( taskName );
    }
}

这里为了还原实际,一般我们会在任务中调用Spring容器中的其他类进行操作,在此我们引入了一个WorkingService 来真正执行任务。

  • 简单的WorkingService
@Service
@Slf4j
public class WorkingService {

    public void work(String taskName){
        log.info("当前任务:" + taskName +" 在线程" + Thread.currentThread().getName() + "上运行");
    }
}
  • 使用TaskScheduler的Bean启动定时任务
@Service
public class SchedulingService {
    private final TaskScheduler taskScheduler; // 可直接注入TaskScheduler的Bean
    private final WorkingService workingService; 

    //构造器注入,免@Autowired
    public SchedulingService(TaskScheduler taskScheduler, WorkingService workingService){ 
        this.taskScheduler = taskScheduler;
        this.workingService = workingService;
    }

    public void schedule(String taskName, String cronExpression){
        //RunnableTask不是一个Bean,不能直接注入workingService,在它的构造器直接传入
        RunnableTask task = new RunnableTask(taskName,workingService);
        CronTrigger cronTrigger = new CronTrigger(cronExpression);
       //api接受实际执行的任务,和定时启动的cron表达式
        taskScheduler.schedule(task,cronTrigger);
    }

    public void scheduleAtFixedRate(String taskName, long period){
        RunnableTask task = new RunnableTask(taskName,workingService);
       //api接受实际执行的任务,和间隔时间
        taskScheduler.scheduleAtFixedRate(task, period);
    }

    public void scheduleWithFixedDelay(String taskName, long delay){
        RunnableTask task = new RunnableTask(taskName,workingService);
       //api接受实际执行的任务,和延迟时间
        taskScheduler.scheduleWithFixedDelay(task, delay);
    }
}
  • 在启动类设置动态配置
@SpringBootApplication
@EnableScheduling
public class DynamicTaskSchedulerApplication {

   public static void main(String[] args) {
      SpringApplication.run(DynamicTaskSchedulerApplication.class, args);
   }

   @Bean
   CommandLineRunner commandLineRunner(SchedulingService schedulingService, WorkingService workingService){
      return args -> {
         schedulingService.schedule("指定时间任务", "50 * * * * THU");
         schedulingService.scheduleAtFixedRate("指定频率任务", 1000);
         schedulingService.scheduleWithFixedDelay("指定延迟任务", 1000);
      } ;
   }
}
  • application.properties的配置
spring.task.scheduling.pool.size=3
spring.task.scheduling.thread-name-prefix=wisely-
  • 启动程序验证
56fc7a8214cb5e912681180512f02ee731f256.png

(此处已添加书籍卡片,请到今日头条客户端查看)

文章出自:​​爱科学的卫斯理​​,如有转载本文请联系爱科学的卫斯理今日头条号。

责任编辑:武晓燕 来源: 今日头条

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK