配置 Job
`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`)需要一个 `JobRepository`。`JobRepository` 的配置通过 `Java 配置` 来处理。
前面的示例展示了一个包含三个 `Step` 实例的 `Job`。Job 相关的构建器还可以包含其他元素,有助于并行化 (`Split`)、声明式流程控制 (`Decision`) 以及流程定义的外部化 (`Flow`)。
`Job` 接口有多种实现。然而,命名空间抽象了配置的差异。它只有三个必需的依赖:一个名称、`JobRepository` 和 `Step` 实例列表。以下示例创建了一个 `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 定义来创建 Step。有关内联声明特定 Step 详细信息的更多选项,请参阅 step configuration 部分。XML 命名空间默认引用 `id` 为 `jobRepository` 的仓库,这是一个合理的默认值。但是,你可以显式覆盖此默认值
<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>
除了 Step 之外,Job 配置还可以包含其他有助于并行化 (`<split>`)、声明式流程控制 (`<decision>`) 和流程定义外部化 (`<flow/>`) 的元素。
可重启性
执行批处理 Job 时的一个关键问题是 `Job` 在重启时的行为。如果特定 `JobInstance` 的 `JobExecution` 已存在,则启动 `Job` 被视为“重启”。理想情况下,所有 Job 都应该能够在上次中断的地方继续运行,但在某些情况下这不可能。在这种情况下,完全由开发者负责确保创建新的 `JobInstance`。 但是,Spring Batch 提供了一些帮助。如果一个 `Job` 不应被重启,而应始终作为新的 `JobInstance` 的一部分运行,则可以将 `restartable` 属性设置为 `false`。
-
Java
-
XML
以下示例展示了如何在 Java 中将 `restartable` 字段设置为 `false`
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.preventRestart()
...
.build();
}
以下示例展示了如何在 XML 中将 `restartable` 字段设置为 `false`
<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
}
首次为不可重启的 Job 创建 `JobExecution` 不会导致问题。然而,第二次尝试会抛出 `JobRestartException` 异常。
拦截 Job 执行
在 `Job` 执行过程中,可能需要在其生命周期的各个事件发生时收到通知,以便运行自定义代码。`SimpleJob` 通过在适当时候调用 `JobListener` 来实现这一点
public interface JobExecutionListener {
void beforeJob(JobExecution jobExecution);
void afterJob(JobExecution jobExecution);
}
你可以通过在 Job 上设置监听器来向 `SimpleJob` 添加 `JobListeners`。
-
Java
-
XML
以下示例展示了如何向 Java Job 定义添加监听器方法
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.listener(sampleListener())
...
.build();
}
以下示例展示了如何向 XML Job 定义添加监听器元素
<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 共享相似但不完全相同的配置,则可以定义一个“父” `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>
有关更详细的信息,请参阅 Inheriting from a Parent Step 部分。
JobParametersValidator
在 XML 命名空间中声明的 Job 或使用 `AbstractJob` 的任何子类的 Job 都可以选择在运行时声明 Job 参数的验证器。当例如需要断言 Job 以所有强制参数启动时,这非常有用。有一个 `DefaultJobParametersValidator`,你可以使用它来约束简单的强制和可选参数的组合。对于更复杂的约束,你可以自己实现该接口。
-
Java
-
XML
验证器的配置通过 Java 构建器支持
@Bean
public Job job1(JobRepository jobRepository) {
return new JobBuilder("job1", jobRepository)
.validator(parametersValidator())
...
.build();
}
验证器的配置通过 XML 命名空间中的 Job 子元素支持,如下例所示
<job id="job1" parent="baseJob3">
<step id="step1" parent="standaloneStep"/>
<validator ref="parametersValidator"/>
</job>
你可以将验证器指定为引用(如前面所示),或作为 `beans` 命名空间中的嵌套 bean 定义。