如何触发计划的Spring批处理作业?

akc*_*soy 10 java spring spring-mvc spring-batch spring-boot

我希望能够使用REST控制器开始工作,然后在作业启动时,它应该按计划运行,直到我再次使用REST停止它.

所以这是我的控制器:

@RestController
public class LauncherController {

    @Autowired
    JobLauncher jobLauncher;

    @Autowired
    Job job;

    @RequestMapping("/launch")
    public String launch() throws Exception {
             ...
            jobLauncher.run(job, jobParameters);
    }
Run Code Online (Sandbox Code Playgroud)

这是Batch conf的一部分:

@Configuration
@EnableBatchProcessing
@EnableScheduling
public class BatchConfiguration {

    @Autowired
    public JobBuilderFactory jobBuilderFactory;

    @Autowired
    public StepBuilderFactory stepBuilderFactory;

    @Scheduled(cron = "0/5 * * * * ?")
    @Bean
    public Job job() {
        return jobBuilderFactory.get("job")
                .incrementer(new RunIdIncrementer())
                .flow(step1())
                .end()
                .build();
    }

    @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
                .<Person, Person> chunk(10)
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .build();
    }
Run Code Online (Sandbox Code Playgroud)

我还设置了属性spring.batch.job.enabled = false,因为我不想在Spring Boot App启动后立即运行作业.

现在我可以打电话给我的Rest api lauch,这个工作仍在运行,但只有一次.调度程序不起作用.我无法确定我应该在哪里定义我的@Scheduled Annotation.

Mac*_*iak 17

我会以某种方式处理它,预定的作业始终运行,但只有当标志设置为true时才会执行某些操作:

@Component
class ScheduledJob {

    private final AtomicBoolean enabled = new AtomicBoolean(false);

    @Scheduled(fixedRate = 1000)
    void execute() {
        if (enabled.get()) {
            // run spring batch here.
        }
    }

    void toggle() {
        enabled.set(!enabled.get());
    }

}
Run Code Online (Sandbox Code Playgroud)

和一个控制器:

@RestController
class HelloController {

    private final ScheduledJob scheduledJob;

    // constructor

    @GetMapping("/launch")
    void toggle() {
        scheduledJob.toggle();
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 如果您处理大量数据并需要以下内容,则需要批处理:事务管理,基于块的处理,声明式I/O,启动/停止/重启,重试/跳过,基于Web的管理界面.如果你只想拥有一个每X或以cron为基础的作业,`@ Scheduled`注释就可以完成这项工作. (2认同)

Ily*_*hin 6

首先,您要定义工作:

@Bean
@Qualifier("fancyScheduledJob")
public Job job() {
    return jobBuilderFactory.get("job")
            .incrementer(new RunIdIncrementer())
            .flow(step1())
            .end()
            .build();
}
Run Code Online (Sandbox Code Playgroud)

第二,你开始执行这项工作:

@Autowired
@Qualifier(value = "fancyScheduledJob")
private Job job;

@Autowired
private JobLauncher jobLauncher;

@Scheduled(cron = "0/5 * * * * ?")
public void launch() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobInstanceAlreadyExistsException, NoSuchJobException {

    jobLauncher.run(job, JobParametersBuilder()
            .addLong("launchTime", System.currentTimeMillis())
            .toJobParameters())
}
Run Code Online (Sandbox Code Playgroud)

另请注意,引入了"launchTime"参数:默认情况下,spring批处理阻止使用相同的参数值启动作业.

虽然您的日程安排非常紧张 - 每5秒钟您应该了解并发性.或者,如果您想确保在每个时刻只执行一个作业实例,您可以配置自定义单线程作业启动器:

@Bean(name = "fancyJobExecutorPool")
public TaskExecutor singleThreadedJobExecutorPool() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(1);
    executor.setMaxPoolSize(1);
    executor.setQueueCapacity(100500);
    executor.setThreadNamePrefix("fancy-job-batch-");
    return executor;
}

@Bean(name = "fancyJobLauncher")
public JobLauncher singleThreadedJobLauncher(JobRepository jobRepository)
{
    SimpleJobLauncher sjl = new SimpleJobLauncher();
    sjl.setJobRepository(jobRepository);
    sjl.setTaskExecutor(singleThreadedJobExecutorPool());
    return sjl;
}
Run Code Online (Sandbox Code Playgroud)

并在启动期间使用此单线程作业启动器.

@Autowired
@Qualifier("fancyJobLauncher")
private JobLauncher jobLauncher;
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您的作业实例将逐个执行(但这不会限制并行执行作业中的步骤).