如何在不使用@Scheduled()注解的情况下在Spring Boot 中调度cron作业

bakd9h0s  于 2023-01-25  发布在  Spring
关注(0)|答案(3)|浏览(160)

在spring Boot 中,我可以通过不对方法使用@Scheduled注解来调度spring作业吗?
我在spring Boot 中使用spring job。我想使用cron表达式来调度一个作业,但是不使用@Scheduled(cron = " ")注解。
我知道我可以在这个方法中安排一个作业,如下所示。

@Scheduled (cron = "0 10 10 10 * ?")

public void execute() { 

   / * some job code * /

}

但是我希望它是动态的,这样我就可以将cron表达式作为用户的输入并对其进行调度。

ki1q1bka

ki1q1bka1#

自从我发现你的问题很有趣,并且以前对这个问题很感兴趣,我就想出了一个工作示例。它完全基于源代码,所以我不知道它是否接近最佳实践。尽管如此,您可能能够根据您的需要调整它。仅供参考,您不一定需要创建一个新的ScheduledTaskRegistrar对象-我认为,由于您的目标是动态调度程序,您不会对纯粹在overwritted方法中定义任务感兴趣。

@SpringBootApplication
public class TaskScheduler implements SchedulingConfigurer, CommandLineRunner {

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

    List<CronTask> cronTasks;

    @Override
    public void run(String... args) throws Exception {
        CronTask task = this.createCronTask(new Runnable() {
            @Override
            public void run() {
                System.out.println(LocalDateTime.now());
            }
        }, "1/10 * * * * *");

        ScheduledTaskRegistrar taskRegistrar = new ScheduledTaskRegistrar();
        taskRegistrar.addCronTask(task);
        configureTasks(taskRegistrar);
        Thread.sleep(51);

        taskRegistrar.destroy();
        taskRegistrar = null;

        ScheduledTaskRegistrar taskRegistrar2 = new ScheduledTaskRegistrar();
        taskRegistrar2.addCronTask(task);
        configureTasks(taskRegistrar2);

    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        // "Calls scheduleTasks() at bean construction time" - docs
        taskRegistrar.afterPropertiesSet();
    }

    public CronTask createCronTask(Runnable action, String expression) {
        return new CronTask(action, new CronTrigger(expression));
    }

}

我有在Azure和其他地方使用cron作业的经验。在Java编程中,我通常使用固定时间的@Scheduled只是为了简单起见。希望这对你有用。

toiithl6

toiithl62#

下面是我的工作示例,如果有人想使用TaskScheduler而不使用@Scheduled Annotation
@Configuration 类

@Configuration
public class SchedulerConfig implements SchedulingConfigurer {

    final Logger LOGGER = LogManager.getLogger(SchedulerConfig.class);

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        LOGGER.debug("Creating Async Task Scheduler");
        scheduledTaskRegistrar.setTaskScheduler(taskScheduler());
    }

    // This is mandatory otherwise it will to be able to find bean of       
    // taskScheduler. Without this it was giving runtime error says, can not find 
    // taskScheduler bean.
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(20); // Better to read it from property file.
        scheduler.setThreadNamePrefix("ThreadScheduler-");
        scheduler.initialize();
        return scheduler;
    }
}

从应用程序类调用的调度程序类。

@Component
public class MyTaskScheduler {

    private TaskScheduler taskScheduler;
    // Here we are auto-wiring taskScheduler, that's why need to create 
   // taskScheduler bean in configuration class
    @Autowired
    public void setScheduler(TaskScheduler scheduler) {
        this.taskScheduler = scheduler;
    }

    public void schedule() {
        taskScheduler.scheduleWithFixedDelay(new Runnable(){
            @Override
            public void run() {
                System.out.println("I am running after every 1 second");
            }
        }, 1000);
    }
}

如果@Configuration注解不起作用,请将@EnableConfigurationProperties放在主运行类中。确保将@EnableScheduling放在Application类中,这样主可运行类看起来会像

@SpringBootApplication
@EnableScheduling
@EnableConfigurationProperties
public class MainApplication implements CommandLineRunner {

    @Autowired
    MyTaskScheduler myTaskScheduler;

    public static void main(String[] args) {
        final Logger logger = LogManager.getLogger(MainApplication.class);
        SpringApplication.run(MainApplication.class, args);
        logger.info("Application started");
    }

    @Override
    public void run(String... args) throws Exception {
        myTaskScheduler.schedule();
    }
}
juzqafwq

juzqafwq3#

这个答案类似于前面的两个答案,但是更加简洁,因为它利用了应用程序上下文中已经提供的调度注册器:

@Configuration
@EnableScheduling
public class Schedule implements SchedulingConfigurer {

    private final transient WorkflowTriggerService workflowTriggerService;

    public Schedule(final WorkflowTriggerService workflowTriggerService) {
        this.workflowTriggerService = workflowTriggerService;
    }

    @Override
    public void configureTasks(final ScheduledTaskRegistrar taskRegistrar) {
        for (final WorkflowTrigger trigger : workflowTriggerService.getWorkflowTriggersWithSchedules()) {
            taskRegistrar.addCronTask(new WorkflowTask(trigger), trigger.getSchedule());
        }
    }

}

服务返回的每个WorkflowTrigger都有自己的cron计划,因此允许动态注册编译时未知的计划任务。

相关问题