当前位置: 首页 > 知识库问答 >
问题:

如何在Spring批处理中动态定义多个作业?

薛浩言
2023-03-14
@Configuration
@EnableBatchProcessing
public class DynamicJobConfigurer extends DefaultBatchConfigurer implements InitializingBean {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private JobRegistry jobRegistry;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private CustomJobDefinitionService customJobDefinitionService;

    private Flow injectedFlow1;
    private Flow injectedFlow2;

    public void setupJobs() throws DuplicateJobException {

        List<JobDefinition> jobDefinitions = customJobDefinitionService.getAllJobDefinitions();

        for (JobDefinition jobDefinition : jobDefinitions) {

            Job job = null;
            if (jobDefinition.getType() == 1) {
                job = jobBuilderFactory.get(jobDefinition.getName())
                        .start(injectedFlow1).build()
                        .build();
            } else if (jobDefinition.getType() == 2) {
                job = jobBuilderFactory.get(jobDefinition.getName())
                        .start(injectedFlow2).build()
                        .build();
            }

            if (job != null) {
                jobRegistry.register(new ReferenceJobFactory(job));
            }
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        setupJobs();
    }

    public void setInjectedFlow1(Flow injectedFlow1) {
        this.injectedFlow1 = injectedFlow1;
    }

    public void setInjectedFlow2(Flow injectedFlow2) {
        this.injectedFlow2 = injectedFlow2;
    }
}

我在XML中定义了注入的流,如下所示:

<batch:flow id="injectedFlow1">

    <batch:step id="InjectedFlow1.Step1" next="InjectedFlow1.Step2">
        <batch:flow parent="InjectedFlow.Step1" />
    </batch:step>

    <batch:step id="InjectedFlow1.Step2">
        <batch:flow parent="InjectedFlow.Step2" />
    </batch:step>

</batch:flow>

因此,正如您所看到的,我实际上是从InitializingBeanafterPropertiesSet()方法启动setupJobs()方法(用于动态创建这些作业定义)。我不确定这是对的。它正在运行,但我不确定是否有一个不同的入口点更适合于这个目的。老实说,我也不知道@configuration注释的意义是什么。

当前遇到的问题是,当我从JobRegistry调用Register()时,它会引发以下IllegalStateException:

若要使用默认的BatchConfigurer,上下文必须包含一个以上的数据源(found 2)。

注意:我的项目实际上定义了两个数据源。第一个是默认的dataSource bean,它连接到Spring批处理使用的数据库。第二个数据源是一个外部数据库,这第二个包含我定义作业列表所需的所有信息。但是主要的一个确实使用了默认名称“DataSource”,所以我不太确定我还可以如何告诉它使用这个名称。

共有1个答案

殷浩慨
2023-03-14

首先,我不推荐使用XML和Java配置的组合。只使用一个,最好是Java一个,因为将XML配置转换为Java配置并不费力。(除非你有一些很好的理由去做--你没有解释)

我并没有单独使用Spring Batch,因为我一直将它与Spring Boot一起使用,并且我有一个项目,在该项目中我定义了多个作业,它对于您所展示的类似代码总是很好地工作。

对于您的问题,有一些类似于这样或这样的答案,它们基本上试图说明您需要编写自己的BatchConfigurer,而不是依赖于默认的BatchConfigurer。

使用Spring Boot,您应该尝试分离作业定义和作业执行。您应该首先尝试只定义作业并初始化Spring上下文,而不启用作业(Spring.batch.job.enabled=false)

在Spring Boot main方法中,当您使用-SpringApplication.run(Application.class,args);...启动应用程序时,您将得到ApplicationContext CTX

现在,您可以从这个上下文中获取相关的bean,通过从属性或命令行等获取名称来启动指定作业&使用joblauncher.run(...)方法。

你可以参考我的这个答案,如果愿意订购的工作执行。您还可以使用Java编写作业调度程序。

重点是,您分离了作业构建/bean配置和作业执行的关注点。

挑战

 类似资料:
  • 是否可以在Spring批处理中动态配置作业? 这是我想做的。我创建了几个不同的,如下所示: FlatFileItemReader 我希望能够在创建批处理作业时动态混合和匹配它们。例如,假设我需要一个有2个步骤的作业。第一步包含一个用于预处理的。第二步将有一个,用于使用我的阅读器/写入器进行基于块的数据处理......类似这样的东西: 在XML中,我可以执行以下操作: 但是我如何像上面一样以编程方式

  • 我们目前正在将一个复杂的spring boot batch+admin UI系统迁移到一个spring-cloud-task基础设施中,该基础设施将被管理云数据流。 作为POC的第一阶段,我们必须能够将所有Spring批处理作业打包在同一个部署JAR下,并且能够使用自定义作业参数一个接一个地运行它们,并且支持某种REST API远程执行作业/任务。 我们删除了所有spring-batch管理依赖项

  • 到目前为止,我正在运行spring批处理,只有一个作业。现在我想运行多个不同的作业,这意味着不同的功能。在我的配置文件中,我配置了两个具有不同id和不同名称的作业。现在我得负责这些工作。你能告诉我怎么跑吗。在这里,我的疑问是在我的java类中,我已经为运行批处理编写了这段代码。 对于其他作业,如何调用jobLauncher的run方法。 我的配置文件是

  • 我在BatchScheduler中有多个计划作业,它在特定时间运行。简单的内置JobLauncher,这是同步的。在自然界中最初使用。现在,我想并行运行这些作业,这样没有作业可以等待其他作业完成。 我在不同的作业上尝试过@Async注释,但都不起作用。 然后,我尝试设置joblauncher.settaskexecutor(新的SimpleAsyncTaskExecutor())。但这并不奏效。

  • 我们正试图建立关于如何在大型IT服务中使用Spring Batch的标准,并具有不同的商业利益。 我们可能会有几个属于不同业务领域的批次。我们已经知道其中一些必须从所有批次通用的表中获取一些参数(即Java和COBOL;例如日期参数)。 我们将实现的Spring批处理作业的数量很难评估。没有重写现有COBOL批次的目标,只要有可能,就鼓励连续流程处理。 一些关于概念证明的问题不时出现,但目前几乎没

  • 我正在使用Spring Boot+Spring Batch(注释),遇到了一个我必须运行2个作业的场景。 我有员工和工资记录,需要使用spring批处理更新。我已经按照本教程spring-batch入门教程为Employee和Salary对象配置了