在每次 Spring 计划 (@Scheduled) 运行之前重置状态

Jam*_*mes 3 spring schedule spring-batch spring-scheduled spring-boot

我有一个需要每天运行的 Spring Boot Batch 应用程序。它读取每日文件,对其数据进行一些处理,并将处理后的数据写入数据库。在此过程中,应用程序保存一些状态,例如要读取的文件(存储在 和 中FlatFileItemReaderJobParameters、运行的当前日期和时间、用于在读取项目之间进行比较的一些文件数据等。

调度的一种选择是使用 Spring,@Scheduled例如:

@Scheduled(cron = "${schedule}")
public void runJob() throws Exception {
    jobRunner.runJob(); //runs the batch job by calling jobLauncher.run(job, jobParameters);
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是在运行之间保持状态。因此,我必须更新要读取的文件、运行的当前日期和时间、清除缓存的文件数据等。

另一种选择是通过 unix cron 作业运行应用程序。这显然可以满足在运行之间清除状态的需要,但我更喜欢将作业调度与应用程序而不是操作系统联系起来(并且更喜欢与操作系统无关)。@Scheduled可以在运行之间重置应用程序状态吗?

Tho*_*ene 5

您始终可以将执行任务(更重要的是保持状态)的代码移至原型范围的 bean 中。然后,每次运行计划的方法时,您都可以从应用程序上下文中检索该 bean 的新实例。

例子

我创建了一个GitHub存储库,其中包含我正在讨论的工作示例,但其要点在于这两个类:

计划任务.java

注意@Scope注释。它指定该组件不应是单例。该randomNumber字段表示我们希望在每次调用时重置的状态。在这种情况下,“重置”意味着生成一个新的随机数,只是为了表明它确实发生了变化。

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
class ScheduledTask {

    private double randomNumber = Math.random();

    void execute() {
        System.out.printf(
            "Executing task from %s. Random number is %f%n",
            this,
            randomNumber
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

任务调度程序.java

通过在 中自动装配ApplicationContext,您可以在方法中使用它scheduledTask来检索 的新实例ScheduledTask

@Component
public class TaskScheduler {

    @Autowired
    private ApplicationContext applicationContext;

    @Scheduled(cron = "0/5 * * * * *")
    public void scheduleTask() {
        ScheduledTask task = applicationContext.getBean(ScheduledTask.class);
        task.execute();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出

运行代码时,下面是它的示例:

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
class ScheduledTask {

    private double randomNumber = Math.random();

    void execute() {
        System.out.printf(
            "Executing task from %s. Random number is %f%n",
            this,
            randomNumber
        );
    }
}
Run Code Online (Sandbox Code Playgroud)