Spring Batch参考文档中文版

4.1 Configuring a Job

Job接口 的实现有多个,但是在配置上命名空间存在着不同。必须依赖的只有三项:名称 nameJobRespositoryStep 的列表:

<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'的引用来作为repository的定义。然而可以向如下显式的覆盖:

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

此外,job配置的step还包含其他的元素,有并发处理(),显示的流程控制()和外化的流程定义()。

4.1.1 Restartablity

执行批处理任务的一个关键问题是要考虑job被重启后的行为。如果一个 JobExecution 已经存在一个特定的 JobInstance ,那么这个job启动时可以认为是“重启”。 理想情况下,所有任务都能够在他们中止的地方启动,但是有许多场景这是不可能的。在这种场景中就要有开发者来决定创建一个新的 JobInstance ,Spring对此也提供了一些帮助。如果job不需要重启,而是总是作为新的 JobInstance 来运行,那么可重启属性可以设置为'false':

<job id="footballJob" restartable="false">
    ...
</job>

设置重启属性restartable为‘false’表示‘这个job不支持再次启动’,重启一个不可重启的job会抛出JobRestartException的异常:

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) {
    //预计抛出JobRestartException异常
}

这个JUnit代码展示了创建一个不可重启的Job后,第一次能够创建 JobExecution ,第二次再创建相同的JobExcution会抛出一个 JobRestartException

4.1.2 Intercepting Job Execution

在job执行过程中,自定义代码能够在生命周期中通过事件通知执行会是很有用的。SimpleJob能够在适当的时机调用JobListener:

public interface JobExecutionListener {

    void beforeJob(JobExecution jobExecution);

    void afterJob(JobExecution jobExecution);

}

JobListener能够添加到SimpleJob中去,作为job的listener元素:

<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执行成功    }
    else if(jobExecution.getStatus() == BatchStatus.FAILED){
        //job执行失败    }
}

对应于这个interface的annotation为:

  • @BeforeJob
  • @AfterJob

4.1.3 Inheriting from a parent Job

如果一组job配置共有相似,但又不是完全相同,那么可以定义一个"父”job,让这些job去继承属性。同Java的类继承一样,子job会把父job的属性和元素合并进来。

下面的例子中,“baseJob”是一个抽象的job定义,只定义了一个监听器列表。名为“job1”的job是一个具体定义,它继承了“baseJob"的监听器,并且与自己的监听器合并,最终生成的job带有两个监听器,以及一个名为”step1“的step。

<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

4.1.4 JobParametersValidator

一个在xml命名空间描述的job或是使用任何抽象job子类的job,可以选择为运行时为job参数定义一个验证器。在job启动时需要保证所有必填参数都存在的场景下,这个功能是很有用的。有一个DefaultJobParametersValidator可以用来限制一些简单的必选和可选参数组合,你也可以实现接口用来处理更复杂的限制。验证器的配置支持使用xml命名空间来作为job的子元素,例如:

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

验证器可以作为一个引用(如上)来定义也可以直接内嵌定义在bean的命名空间中。