如何在春季批处理中创建动态多个作业

时间:2020-08-11 06:05:20

标签: java spring spring-boot spring-batch spring-batch-job-monitoring

我创建了多个作业,并且我正在循环运行多个作业,我要求依次运行这些作业,但是所有步骤的项目读取器都在运行,然后所有作业的项目写入器都在按顺序运行,是否有解决方案这样,当一项工作的项读取器和项编写器完成时,控制权就转到了另一项工作。

示例代码如下

public void jobprocess() throws Exception {
        List<Job> jobList = BatchJob.fetchAllJobs();
        for(Job job:jobList){            
            jobLauncher.run(job, params);
        }

    }
    
    public List<Job> fetchAllJobs() throws Exception {
            List<Object> list = service.findAll();
            List<Job> jobBuilderList = new ArrayList<>();
            int i = 0;
            for(Object obj:list){
    
                Step step = stepBuilderFactory.get("step"+i)
                    .<Student, Student>chunk(500)
                    .reader(ListItemReaderV2(obj))
                    .processor(Processor)
                    .writer(Writer)
                    .build();
    
                jobBuilderList.add(jobBuilderFactory.get("job"+i)
                    .incrementer(new RunIdIncrementer())
                    .listener(this)
                    .start(step)
                    .build());
                i++;
    
            }
            return jobBuilderList;
        }

2 个答案:

答案 0 :(得分:0)

您应该构造一个超级作业,该作业将您的多个作业封装为步骤。这样,您可以要求Spring batch按顺序运行这些步骤(因此您的作业)。在Spring批处理中,有一个特定的步骤(JobStep)可以这样做:


public void  jobprocess() throws Exception {
    jobLauncher.run(superJob(), params);
}

public Job superJob(){
   List<Step> stepList = BatchJob.fetchAllJobs().stream()
                                           .map(j-> stepBuilderFactory.get(j.getName())
                                                        .job(j)
                                                        .build()
                                            ).collect(Collectors.toList());
   SimpleJobBuilder simpleJobBuilder=jobBuilderFactory.get("superJob")
                                                      .start(stepList.get(0));
   for(int i = 1; i < stepList.size() ; i++){
        simpleJobBuilder.next(stepList.get(i))
   }
   return simpleJobBuilder.build();
}

旧式循环编码的信息:这是排除stepList的第一项的最简单方法。注意,我使用了默认行为,它将默认的父工作参数注入每个JobStep中(参见https://docs.spring.io/spring-batch/docs/4.2.x/api/org/springframework/batch/core/step/job/JobStep.html#setJobParametersExtractor-org.springframework.batch.core.step.job.JobParametersExtractor-

答案 1 :(得分:0)

经过大量实验,我发现此问题是由于在作业类中使用ListItemReader()方法造成的。

ListItemReader<Object> listItemReader(object obj) {
 return new ListItemReader<>(service.getList()); }

在上述实现中,listItemReader()方法甚至在作业开始之前就调用,而job在执行listItemReader()方法之后开始。

现在,我通过实现ItemReader接口创建了一个单独的阅读器类,现在我不返回ListItemReader,而是返回Only ItemReader。 通过执行此操作,我的作业可以按预期运行。

阅读器类的虚拟代码为:

public class ReaderClass implements ItemReader<Object> {

    final private DataService dataService;

    final private entity entity;

    private List<Object> responseList;

    private int count = 0;

    @Override
    public Product read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        if(responseList==null){
            responseList = DataService.fetchData(entity);
        }        
        Object obj = null;
        if (count < responseList.size()) {
            obj = responseList.get(count);
            count++;
        }
        return obj;
    }

}