配置任务

Job 接口有多种实现。然而,这些实现被抽象在提供的构建器(用于 Java 配置)或 XML 命名空间(用于基于 XML 的配置)之后。以下示例展示了 Java 和 XML 两种配置方式:spring-doc.cadn.net.cn

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

一个Job(以及通常其中的任何Step)需要一个JobRepositoryspring-doc.cadn.net.cn

前面的示例展示了一个由三个 Step 实例组成的 Job。与作业相关的构建器还可以包含其他元素,以支持并行化(Split)、声明式流程控制(Decision)以及流程定义的外部化(Flow)。spring-doc.cadn.net.cn

Job 接口有多种实现。然而,命名空间抽象了配置上的差异。它只有三个必需的依赖项:一个名称、JobRepository 以及一个 Step 实例列表。以下示例创建了一个 footballJobspring-doc.cadn.net.cn

<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 的存储库,这是一个合理的默认值。但是,您可以显式地覆盖此默认值:spring-doc.cadn.net.cn

<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/>)。spring-doc.cadn.net.cn

可重启性

执行批处理作业时的一个关键问题涉及 Job 在重启时的行为。如果特定的 JobInstance 已经存在一个 JobExecution,则启动 Job 被视为“重启”。理想情况下,所有作业都应能够从上次停止的位置继续执行,但在某些场景下这是无法实现的。 在此场景中,完全由开发人员负责确保创建一个新的 JobInstance 不过,Spring Batch 确实提供了一些帮助。如果某个 Job 绝不应被重启,而应始终作为新 JobInstance 的一部分运行,您可以将 restartable 属性设置为 falsespring-doc.cadn.net.cn

以下示例展示了如何在 Java 中将 restartable 字段设置为 falsespring-doc.cadn.net.cn

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

以下示例展示了如何在 XML 中将 restartable 字段设置为 falsespring-doc.cadn.net.cn

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

换一种说法,将 restartable 设置为 false 意味着“此Job不支持再次启动”。尝试重启一个不可重启的 Job 会导致抛出 JobRestartException。 以下 JUnit 代码会引发该异常:spring-doc.cadn.net.cn

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 不会引发任何问题。然而,第二次 尝试将抛出 JobRestartExceptionspring-doc.cadn.net.cn

拦截作业执行

Job的执行过程中,可能需要获知其生命周期中的各种事件,以便运行自定义代码。 SimpleJob通过在适当时机调用 JobListener来实现这一点:spring-doc.cadn.net.cn

public interface JobExecutionListener {

    void beforeJob(JobExecution jobExecution);

    void afterJob(JobExecution jobExecution);
}

您可以通过在作业上设置监听器,将 JobListeners 添加到 SimpleJobspring-doc.cadn.net.cn

以下示例展示了如何将监听器方法添加到 Java 作业定义中:spring-doc.cadn.net.cn

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

以下示例展示了如何在 XML 作业定义中添加监听器元素:spring-doc.cadn.net.cn

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 中获取该信息:spring-doc.cadn.net.cn

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

与此接口对应的注解是:spring-doc.cadn.net.cn

从父作业继承

如果一组作业共享相似但不完全相同的配置,那么定义一个“父” Job,以便具体的 Job实例可以从中继承属性,可能会有所帮助。类似于 Java 中的类继承,“子” Job会将其元素和属性与父级的元素和属性相结合。spring-doc.cadn.net.cn

在以下示例中,baseJob 是一个抽象的Job定义,仅定义了监听器列表。Jobjob1)是一个具体定义,它从baseJob继承监听器列表,并将其与自身的监听器列表合并,从而生成一个包含两个监听器和一个Stepstep1)的Jobspring-doc.cadn.net.cn

<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>

有关更详细的信息,请参阅关于 从父步骤继承 的章节。spring-doc.cadn.net.cn

作业参数验证器

在 XML 命名空间中声明的作业,或使用任何 AbstractJob 子类的作业,可以选择性地在运行时为作业参数声明一个验证器。例如,当您需要断言作业启动时包含了所有必需的参数时,这将非常有用。您可以使用一个 DefaultJobParametersValidator 来约束简单必需参数和可选参数的组合。对于更复杂的约束,您可以自行实现该接口。spring-doc.cadn.net.cn

验证器的配置可通过 Java 构建器支持:spring-doc.cadn.net.cn

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

验证器的配置可以通过 XML 命名空间支持,作为 job 的子元素,如下例所示:spring-doc.cadn.net.cn

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

您可以将验证器指定为引用(如前所示),或作为 beans 命名空间中的嵌套 Bean 定义。spring-doc.cadn.net.cn