配置作业

Job 接口有多个实现。但是,这些实现被提供的构建器(用于 Java 配置)或 XML 命名空间(用于基于 XML 的配置)抽象掉了。以下示例显示了 Java 和 XML 配置

  • Java

  • XML

@Bean
public Job footballJob(JobRepository jobRepository) {
    return new JobBuilder("footballJob", jobRepository)
                     .start(playerLoad())
                     .next(gameLoad())
                     .next(playerSummarization())
                     .build();
}

Job(通常还有其中的任何 Step)需要 JobRepositoryJobRepository 的配置通过 Java 配置 处理。

前面的示例说明了一个 Job,它由三个 Step 实例组成。与作业相关的构建器还可以包含其他元素,这些元素有助于并行化(Split)、声明性流程控制(Decision)和流程定义的外化(Flow)。

Job 接口有多个实现。但是,命名空间抽象掉了配置中的差异。它只有三个必需的依赖项:名称、JobRepositoryStep 实例列表。以下示例创建了一个 footballJob

<job id="footballJob">
    <step id="playerload"          parent="s1" next="gameLoad"/>
    <step id="gameLoad"            parent="s2" next="playerSummarization"/>
    <step id="playerSummarization" parent="s3"/>
</job>

前面的示例使用父 bean 定义来创建步骤。有关在内联声明特定步骤详细信息时的更多选项,请参见 步骤配置 部分。XML 命名空间默认为引用 idjobRepository 的存储库,这是一个明智的默认值。但是,你可以显式覆盖此默认值

<job id="footballJob" job-repository="specialRepository">
    <step id="playerload"          parent="s1" next="gameLoad"/>
    <step id="gameLoad"            parent="s3" next="playerSummarization"/>
    <step id="playerSummarization" parent="s3"/>
</job>

除了步骤以外,作业配置还可以包含其他元素,这些元素有助于并行化 (<split>)、声明性流程控制 (<decision>) 和流程定义的外化 (<flow/>)。

可重启性

执行批处理作业时的一个关键问题涉及 Job 在重新启动时的行为。如果特定 JobInstance 已经存在 JobExecution,则 Job 的启动被视为“重新启动”。理想情况下,所有作业都应该能够从中断处启动,但有些情况下这是不可能的。在这种情况下,完全由开发人员确保创建新的 JobInstance但是,Spring Batch 确实提供了一些帮助。如果 Job 永远不应重新启动,但应始终作为新 JobInstance 的一部分运行,则可以将 restartable 属性设置为 false

  • Java

  • XML

以下示例演示如何在 Java 中将 restartable 字段设置为 false

Java 配置
@Bean
public Job footballJob(JobRepository jobRepository) {
    return new JobBuilder("footballJob", jobRepository)
                     .preventRestart()
                     ...
                     .build();
}

以下示例演示如何在 XML 中将 restartable 字段设置为 false

XML 配置
<job id="footballJob" restartable="false">
    ...
</job>

换句话说,将 restartable 设置为 false 意味着“此 Job 不支持再次启动”。重新启动不可重启的 Job 会导致抛出 JobRestartException。以下 Junit 代码会导致抛出异常

Job job = new SimpleJob();
job.setRestartable(false);

JobParameters jobParameters = new JobParameters();

JobExecution firstExecution = jobRepository.createJobExecution(job, jobParameters);
jobRepository.saveOrUpdate(firstExecution);

try {
    jobRepository.createJobExecution(job, jobParameters);
    fail();
}
catch (JobRestartException e) {
    // expected
}

第一次尝试为不可重启作业创建 JobExecution 不会造成任何问题。但是,第二次尝试会抛出 JobRestartException

拦截作业执行

Job 执行过程中,可能需要了解其生命周期中的各种事件,以便可以运行自定义代码。SimpleJob 通过在适当的时间调用 JobListener 来允许这样做

public interface JobExecutionListener {

    void beforeJob(JobExecution jobExecution);

    void afterJob(JobExecution jobExecution);
}

可以通过在作业上设置侦听器来将 JobListeners 添加到 SimpleJob

  • Java

  • XML

以下示例演示如何将侦听器方法添加到 Java 作业定义

Java 配置
@Bean
public Job footballJob(JobRepository jobRepository) {
    return new JobBuilder("footballJob", jobRepository)
                     .listener(sampleListener())
                     ...
                     .build();
}

以下示例演示如何将侦听器元素添加到 XML 作业定义

XML 配置
<job id="footballJob">
    <step id="playerload"          parent="s1" next="gameLoad"/>
    <step id="gameLoad"            parent="s2" next="playerSummarization"/>
    <step id="playerSummarization" parent="s3"/>
    <listeners>
        <listener ref="sampleListener"/>
    </listeners>
</job>

请注意,无论 Job 成功与否,都会调用 afterJob 方法。如果您需要确定成功或失败,则可以从 JobExecution 中获取该信息

public void afterJob(JobExecution jobExecution){
    if (jobExecution.getStatus() == BatchStatus.COMPLETED ) {
        //job success
    }
    else if (jobExecution.getStatus() == BatchStatus.FAILED) {
        //job failure
    }
}

与此接口相对应的注释是

  • @BeforeJob

  • @AfterJob

继承父作业

如果一组作业共享相似但并非完全相同的配置,则定义一个“父”Job可能会有所帮助,具体Job实例可以从中继承属性。类似于 Java 中的类继承,“子”Job将其元素和属性与父元素和属性结合在一起。

在以下示例中,baseJob是一个抽象Job定义,仅定义一个侦听器列表。Job (job1)是一个具体定义,它从baseJob继承侦听器列表,并将其与它自己的侦听器列表合并,以生成一个具有两个侦听器和一个Step (step1)的Job

<job id="baseJob" abstract="true">
    <listeners>
        <listener ref="listenerOne"/>
    <listeners>
</job>

<job id="job1" parent="baseJob">
    <step id="step1" parent="standaloneStep"/>

    <listeners merge="true">
        <listener ref="listenerTwo"/>
    <listeners>
</job>

有关更多详细信息,请参阅继承父步骤部分。

JobParametersValidator

在 XML 命名空间中声明的作业或使用AbstractJob的任何子类的作业可以选择在运行时声明作业参数的验证器。这很有用,例如,当您需要断言作业已使用其所有必需参数启动时。有一个DefaultJobParametersValidator,您可以使用它来约束简单必需参数和可选参数的组合。对于更复杂的约束,您可以自己实现该接口。

  • Java

  • XML

通过 Java 构建器支持验证器的配置

@Bean
public Job job1(JobRepository jobRepository) {
    return new JobBuilder("job1", jobRepository)
                     .validator(parametersValidator())
                     ...
                     .build();
}

通过作业的子元素通过 XML 命名空间支持验证器的配置,如下例所示

<job id="job1" parent="baseJob3">
    <step id="step1" parent="standaloneStep"/>
    <validator ref="parametersValidator"/>
</job>

您可以将验证器指定为引用(如前所示)或作为beans命名空间中的嵌套 bean 定义。