配置作业
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
。与之相关的构建器还可以包含其他元素,这些元素有助于并行化(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 定义来创建步骤。有关声明特定步骤详细信息的更多选项,请参阅 步骤配置 部分。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>
除了步骤之外,作业配置还可以包含其他元素,这些元素有助于并行化(<split>
)、声明性流程控制(<decision>
)和流程定义的外部化(<flow/>
)。
重启能力
在执行批处理任务时,一个关键问题涉及到 Job
在重启时的行为。如果某个特定的 JobInstance
已经存在一个 JobExecution
,那么启动一个 Job
就会被视为“重启”。理想情况下,所有任务都应该能够从上次中断的地方继续执行,但在某些场景下这是不可能实现的。在这种情况下,完全由开发人员确保创建一个新的 JobInstance
。然而,Spring Batch 确实提供了一些帮助。如果一个 Job
不应被重启,而应始终作为新的 JobInstance
的一部分运行,您可以将可重启属性设置为 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
}
首次为不可重启的作业创建 JobExecution
时不会出现问题。但是,第二次尝试会抛出 JobRestartException
。
拦截作业执行
在 Job
执行的过程中,可能需要在其生命周期中的各种事件中收到通知,以便运行自定义代码。SimpleJob
通过在适当的时间调用 JobListener
来实现这一功能:
public interface JobExecutionListener {
void beforeJob(JobExecution jobExecution);
void afterJob(JobExecution jobExecution);
}
你可以通过在作业上设置监听器来为 SimpleJob
添加 JobListeners
。
- Java
- XML
下面的示例展示了如何向 Java 作业定义中添加监听器方法:
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.listener(sampleListener())
...
.build();
}
下面的示例展示了如何向 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
可能会有所帮助,具体的 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 定义。