如何使用 ThreadPoolTask​​Scheduler 动态调度 Spring 批处理作业

How to dynamically schedule a Spring Batch job with ThreadPoolTaskScheduler

我有一个 Spring 批处理应用程序,我想在其中安排作业调用。

构建时不知道调度间隔,所以我不能只用 @Scheduled.This 注释我的作业导致我使用 ThreadPoolTask​​Scheduler。

问题是方法调度将 Runnable 作为参数。是否有可能以这种方式安排工作? 我可以直接从以下服务调用作业,但无法安排它。

这是我的问题的背景,我试图让它变得简单:

@Service
public class ScheduledProcessor{
    private final ThreadPoolTaskScheduler  threadPoolTaskScheduler;
    private Application application;   
    @Autowired
    public ScheduledProcessor(ThreadPoolTaskScheduler threadPoolTaskScheduler, Application application){
        this.threadPoolTaskScheduler = threadPoolTaskScheduler;
        this.application = application;
        scheduledTasks = new ArrayList();


        Trigger trigger = new CronTrigger("0/6 * * * * *");
//Here I am trying to schedule my job.
//The following line is wrong because a Job can't be cast to a Runnable but I wanted to show the intended behaviour.            
        threadPoolTaskScheduler.schedule((Runnable) application.importUserjob, trigger);
        System.out.println("Job launch !");
    }

这里是 JobBuilderFactory:

@Bean
public Job importUserJob(JobBuilderFactory jobs, Step s1, Step s2) {
    return jobs.get("importUserJob")
            .incrementer(new RunIdIncrementer())
            .flow(s1)
            .end()
            .build();
}

我知道(好吧,我什至不确定)我不能直接将 Job 转换为 Runnable,但是否可以以任何方式转换它?或者你能给我一些关于使用什么来动态安排 spring 批处理作业的建议吗?

万一改变了什么,我还需要能够重新启动/跳过我的步骤,就像我目前可以使用 threadPoolTask​​Scheduler 一样。

提前感谢您提供的任何帮助或提示。

我终于知道怎么做了!

我创建了一个实现 Runnable 的 class(为了方便起见,扩展了 Thread,这避免了实现所有 Runnable classes 的需要)。

@Component
public class MyRunnableJob extends Thread implements Runnable{

    private Job job;
    private JobParameters jobParameters;
    private final JobOperator jobOperator;

    @Autowired
    public MyRunnableJob(JobOperator jobOperator) {
        this.jobOperator = jobOperator;
    }

    public void setJob(Job job){
        this.job=job;
    }

    @Override
    public void run(){
        try {
            String dateParam = new Date().toString();
            this.jobParameters = new JobParametersBuilder().addString("date", dateParam).toJobParameters();
            System.out.println("jobName : "+job.getName()+" at "+dateParam);

            jobOperator.start(job.getName(), jobParameters.toString());
        } catch (NoSuchJobException | JobInstanceAlreadyExistsException | JobParametersInvalidException ex) {
            Logger.getLogger(MyRunnableJob.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

在我的 ScheduledProcessor class 中,我将 Job 设置为 myRunnable class,然后将其作为 schedule 方法的参数传递。

public class SchedulingProcessor {

    //Autowired fields :
    private final JobLauncher jobLauncher;
    private final Job importUserJob;
    private final ThreadPoolTaskScheduler  threadPoolTaskScheduler;
    private final MyRunnableJob myRunnableJob;


    //Other fields :
    private List<ScheduledFuture> scheduledTasks;


    @Autowired
    public SchedulingProcessor(JobLauncher jobLauncher, Job importUserJob, ThreadPoolTaskScheduler  threadPoolTaskScheduler, MyRunnableJob myRunnableJob) throws Exception {
        this.jobLauncher=jobLauncher;
        this.importUserJob=importUserJob;
        this.threadPoolTaskScheduler=threadPoolTaskScheduler;
        this.myRunnableJob=myRunnableJob;
        Trigger trigger = new CronTrigger("0/6 * * * * *");
        myRunnableJob.setJob(this.importUserJob);
        scheduledTasks = new ArrayList();
        scheduledTasks.add(this.threadPoolTaskScheduler.schedule((Runnable) myRunnableJob, trigger));
    }        
}

scheduledTasks 列表只是为了控制我刚刚安排的任务。

这个技巧使我能够动态地(感谢 ThreadPoolTask​​Scheduler)调度 Spring 封装在 class 实现 Runnable 中的批处理作业。希望能帮到跟我一样的人

这是从您的 spring 上下文中触发它们的另一种方法。

    Job emailJob = (Job) applicationContext.getBean("xyzJob");
    JobLauncher launcher = (JobLauncher) applicationContext
            .getBean("jobLauncher");
    launcher.run(emailJob, new JobParameters());