对于最新稳定版本,请使用Spring Batch Documentation 6.0.0spring-doc.cadn.net.cn

控制阶梯流量

在拥有工作中能够将步骤归类,也意味着能够 以控制工作如何“从一个步骤”流向另一个步骤“。失败不 必然意味着工作应该会失败。此外,还可能存在多种类型 决定了哪种“成功”的接下来应该被处决。这取决于 组步骤配置中,某些步骤甚至可能根本无法处理。spring-doc.cadn.net.cn

流程定义中的步进豆方法代理

步骤实例必须在流程定义中唯一。当一个步骤在流程定义中具有多个结果时, 重要的是,该步骤的同一实例传递给流定义方法(开始,,等等)。 否则,流程执行可能会出现意外。spring-doc.cadn.net.cn

在以下示例中,步骤作为参数注入到流程或作业豆定义方法中。这种依赖注入方式保证了流程定义中步骤的唯一性。 然而,如果流程通过调用带有注释的步定义方法定义,则@Bean那么如果禁用BEAN方法代理(即),步骤可能不唯一@Configuration(proxyBeanMethods = false)). 如果偏好豆间注入方式,则必须启用豆子方法代理。spring-doc.cadn.net.cn

有关 Spring Framework 中豆子方法代理的更多细节,请参阅“使用@Configuration注释”部分。spring-doc.cadn.net.cn

顺序流

最简单的流程场景是所有步骤顺序执行的作业,如 下图显示:spring-doc.cadn.net.cn

顺序流
图1。顺序流

这可以通过使用下一个.spring-doc.cadn.net.cn

以下示例展示了如何使用Next()Java 中的方法:spring-doc.cadn.net.cn

Java 配置
@Bean
public Job job(JobRepository jobRepository, Step stepA, Step stepB, Step stepC) {
	return new JobBuilder("job", jobRepository)
				.start(stepA)
				.next(stepB)
				.next(stepC)
				.build();
}

以下示例展示了如何使用下一个XML 中的属性:spring-doc.cadn.net.cn

XML 配置
<job id="job">
    <step id="stepA" parent="s1" next="stepB" />
    <step id="stepB" parent="s2" next="stepC"/>
    <step id="stepC" parent="s3" />
</job>

在上述情景中,stepA先跑,因为它是第一上市。如果stepA正常完成,stepB跑道,等等。然而,如果步骤A失败 整个工作失败和stepB未执行。spring-doc.cadn.net.cn

使用 Spring Batch XML 命名空间,配置中列出的第一步总是工作.其他步骤元素的顺序则不 但第一步必须始终出现在XML中。

条件流

在上述例子中,只有两种可能:spring-doc.cadn.net.cn

  1. 成功了,下一个应该被处决。spring-doc.cadn.net.cn

  2. 失败了,因此,工作应该会失败。spring-doc.cadn.net.cn

在许多情况下,这可能就足够了。然而,如果有这样一个情景, 失败应该会触发不同的情况,而不是导致失败?这 下图展示了这样的流动:spring-doc.cadn.net.cn

条件流
图2。条件流

Java API 提供了一套流畅的方法,让你可以指定流程和作内容 当步骤失败时。以下示例展示了如何指定一步(stepA) 然后 继续进行两个不同的步骤之一(stepBstepC),取决于stepA成功:spring-doc.cadn.net.cn

Java 配置
@Bean
public Job job(JobRepository jobRepository, Step stepA, Step stepB, Step stepC) {
	return new JobBuilder("job", jobRepository)
				.start(stepA)
				.on("*").to(stepB)
				.from(stepA).on("FAILED").to(stepC)
				.end()
				.build();
}

为了处理更复杂的场景,Spring Batch XML 命名空间允许你定义过渡 步骤元素中的元素。其中一个变迁是下一个元素。就像下一个属性,该下一个元素表示工作自 下一个执行。然而,与属性不同,任意数量的下一个元素允许于 这是理所当然的,且在失败情况下没有默认行为。这意味着,如果 使用了转换元素,所有行为转移必须是 明确定义。还要注意,单一步不可能同时有下一个属性和 一个过渡元素。spring-doc.cadn.net.cn

下一个元素指定匹配的模式和下一步执行的步骤,如 以下示例展示了:spring-doc.cadn.net.cn

XML 配置
<job id="job">
    <step id="stepA" parent="s1">
        <next on="*" to="stepB" />
        <next on="FAILED" to="stepC" />
    </step>
    <step id="stepB" parent="s2" next="stepC" />
    <step id="stepC" parent="s3" />
</job>

使用 Java 配置时,on()该方法使用简单的模式匹配方案 匹配退出状态这由执行.spring-doc.cadn.net.cn

使用 XML 配置时,转移元素的属性使用简单的 模式匹配方案以匹配退出状态这由执行.spring-doc.cadn.net.cn

该图案中仅允许两个特殊字符:spring-doc.cadn.net.cn

例如比赛计数C?T比赛但又不是计数.spring-doc.cadn.net.cn

虽然 上转移元素的数量没有限制,如果执行结果为退出状态不被元素覆盖的 框架抛出一个异常,并且工作失败。框架会自动排序 从最具体到最不具体的过渡。这意味着,即使排序 被替换为stepA在上述例子中,一个退出状态失败还是会去 自stepC.spring-doc.cadn.net.cn

批次状态与退出状态

在配置工作对于条件流,理解 区别批处理状态退出状态.批处理状态是一个枚举,使得 是两者的性质作业执行步执行框架将 用于 记录A的状态工作.它可以是以下数值之一:完成,开始,开始,停止,停止,失败,被遗弃的未知.大多数都不言自明:完成是当一步时所设定的状态 或者任务已成功完成,失败当它失败时被设置,依此类推。spring-doc.cadn.net.cn

以下示例包含在使用 Java 配置时:spring-doc.cadn.net.cn

...
.from(stepA).on("FAILED").to(stepB)
...

以下示例包含下一个在使用 XML 配置时:spring-doc.cadn.net.cn

<next on="FAILED" to="stepB" />

乍一看,似乎参考文献批处理状态关于自 它本该属于这里。然而,它实际上引用了退出状态关于.作为 顾名思义退出状态表示 的状态等执行完毕。spring-doc.cadn.net.cn

使用 Java 配置时,on()上述方法如下所示 Java 配置示例引用了 的出口代码退出状态.spring-doc.cadn.net.cn

更具体地说,当使用 XML 配置时,下一个在 前面的XML配置示例引用了退出状态.spring-doc.cadn.net.cn

英文中写着:“如果退出代码失败,则进入步骤B”。默认情况下,退出 代码总是与批处理状态对于,这也是为什么前文条目 工程。但是,如果出口代码需要不同呢?一个很好的例子来自 Sample项目中的跳过样本工作:spring-doc.cadn.net.cn

以下示例展示了如何在 Java 中使用不同的退出代码:spring-doc.cadn.net.cn

Java 配置
@Bean
public Job job(JobRepository jobRepository, Step step1, Step step2, Step errorPrint1) {
	return new JobBuilder("job", jobRepository)
			.start(step1).on("FAILED").end()
			.from(step1).on("COMPLETED WITH SKIPS").to(errorPrint1)
			.from(step1).on("*").to(step2)
			.end()
			.build();
}

以下示例展示了如何在 XML 中使用不同的退出码:spring-doc.cadn.net.cn

XML 配置
<step id="step1" parent="s1">
    <end on="FAILED" />
    <next on="COMPLETED WITH SKIPS" to="errorPrint1" />
    <next on="*" to="step2" />
</step>

第一步有三种可能:spring-doc.cadn.net.cn

上述配置是可行的。不过,需要根据以下情况更改退出代码 执行时跳过记录的条件,如下示例所示:spring-doc.cadn.net.cn

public class SkipCheckingListener implements StepExecutionListener {
    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        String exitCode = stepExecution.getExitStatus().getExitCode();
        if (!exitCode.equals(ExitStatus.FAILED.getExitCode()) &&
            stepExecution.getSkipCount() > 0) {
            return new ExitStatus("COMPLETED WITH SKIPS");
        } else {
            return null;
        }
    }
}

前面的代码是StepExecutionListener首先要检查以确保是 成功,然后检查跳过是否计入步执行高于 0. 如果满足这两个条件,则退出状态出口代码为并以跳跃补全被归还。spring-doc.cadn.net.cn

停止配置

讨论结束后批处理状态退出状态, 有人可能会好奇批处理状态退出状态确定了工作. 虽然这些状态是为由执行的代码, 该项目的状态工作根据配置确定。spring-doc.cadn.net.cn

到目前为止,所有讨论的岗位配置至少有一个最终方案跟 没有过渡。spring-doc.cadn.net.cn

在以下 Java 示例中,之后执行,执行工作结束:spring-doc.cadn.net.cn

@Bean
public Job job(JobRepository jobRepository, Step step1) {
	return new JobBuilder("job", jobRepository)
				.start(step1)
				.build();
}

在以下XML示例中,在执行,执行工作结束:spring-doc.cadn.net.cn

<step id="step1" parent="s3"/>

如果对 a 没有转移定义工作定义为 遵循:spring-doc.cadn.net.cn

  • 如果结尾为退出状态失败批处理状态退出状态之 这工作两者皆为失败.spring-doc.cadn.net.cn

  • 否则,批处理状态退出状态关于工作两者皆为完成.spring-doc.cadn.net.cn

虽然这种终止批处理作业的方法对于某些批处理作业来说已经足够,例如: 可能需要简单的顺序步骤作业,自定义的作业停止场景。为 为此,Spring Batch提供了三个过渡元素来阻止工作(在 对下一个元素这是我们之前讨论过的)。 这些停止元素中的每一个都阻止了工作具有批处理状态.是的 重要的是,停止转移元素对批处理状态退出状态任何步骤工作.这些元素只影响 最终状态工作.例如,作业中的每一步都可能 一个失败但要让该职位拥有完成.spring-doc.cadn.net.cn

以阶梯结尾

配置步末端指示工作停止时批处理状态完成.一个工作该事件已以完成无法重启(框架抛弃 一个JobInstanceAlreadyCompleteException).spring-doc.cadn.net.cn

使用 Java 配置时,结束该方法用于完成此任务。这结束方法 同时允许可选退出现状你可以用来自定义退出状态关于工作.如果没有退出现状价值被提供,退出状态完成默认情况下,要匹配批处理状态.spring-doc.cadn.net.cn

使用 XML 配置时,可以使用结束该任务的元素。这结束元素 同时允许可选出口代码属性,你可以用来自定义退出状态关于工作.如果没有出口代码属性给定,且退出状态完成默认情况下,要匹配批处理状态.spring-doc.cadn.net.cn

考虑以下情景:如果步骤2失败,工作以 a 闭音批处理状态完成以及退出状态完成步骤3不跑。 否则,执行会移动到步骤3.注意,如果步骤2失败,工作莫 可重启(因为状态是完成).spring-doc.cadn.net.cn

以下示例展示了Java中的场景:spring-doc.cadn.net.cn

@Bean
public Job job(JobRepository jobRepository, Step step1, Step step2, Step step3) {
	return new JobBuilder("job", jobRepository)
				.start(step1)
				.next(step2)
				.on("FAILED").end()
				.from(step2).on("*").to(step3)
				.end()
				.build();
}

以下示例展示了XML中的场景:spring-doc.cadn.net.cn

<step id="step1" parent="s1" next="step2">

<step id="step2" parent="s2">
    <end on="FAILED"/>
    <next on="*" to="step3"/>
</step>

<step id="step3" parent="s3">

步骤失败

将步骤配置为在某一点失败,指示工作停止时批处理状态失败.与终点不同,失败是工作并不能阻止工作避免被重新开始。spring-doc.cadn.net.cn

使用 XML 配置时,失败element 还允许可选出口代码属性 可用于自定义退出状态关于工作.如果没有出口代码属性给定,且退出状态失败默认情况下,要匹配批处理状态.spring-doc.cadn.net.cn

考虑以下情景:如果步骤2失败,工作以 a 闭音批处理状态失败以及退出状态提前终止步骤3不 执行。否则,执行会移动到步骤3.此外,如果步骤2失败和工作重新开始,执行重新开始。步骤2.spring-doc.cadn.net.cn

以下示例展示了Java中的场景:spring-doc.cadn.net.cn

Java 配置
@Bean
public Job job(JobRepository jobRepository, Step step1, Step step2, Step step3) {
	return new JobBuilder("job", jobRepository)
			.start(step1)
			.next(step2).on("FAILED").fail()
			.from(step2).on("*").to(step3)
			.end()
			.build();
}

以下示例展示了XML中的场景:spring-doc.cadn.net.cn

XML 配置
<step id="step1" parent="s1" next="step2">

<step id="step2" parent="s2">
    <fail on="FAILED" exit-code="EARLY TERMINATION"/>
    <next on="*" to="step3"/>
</step>

<step id="step3" parent="s3">

在某个步骤停止工作

配置作业在某一特定步骤停止,指示工作停止时批处理状态停止.阻止工作可以暂时中断处理, 这样操作员才能在重新开始工作.spring-doc.cadn.net.cn

使用 Java 配置时,停止再开始方法需要重新启动属性 该步骤指定了作业重启时执行应从哪一步开始。spring-doc.cadn.net.cn

使用 XML 配置时,a元素需要一个重新启动指定 的属性 执行应在工作是重启的。spring-doc.cadn.net.cn

考虑以下情景:如果第一步结尾为完成那就工作了 停止。一旦重启,执行就开始于步骤2.spring-doc.cadn.net.cn

以下示例展示了Java中的场景:spring-doc.cadn.net.cn

@Bean
public Job job(JobRepository jobRepository, Step step1, Step step2) {
	return new JobBuilder("job", jobRepository)
			.start(step1).on("COMPLETED").stopAndRestart(step2)
			.end()
			.build();
}

以下列表展示了该场景的XML格式:spring-doc.cadn.net.cn

<step id="step1" parent="s1">
    <stop on="COMPLETED" restart="step2"/>
</step>

<step id="step2" parent="s2"/>

程序化流程决策

在某些情况下,更多信息会比退出状态可能需要决定 下一步执行哪个步骤。在这种情况下,一个JobExecutionDecider可以用来辅助 在判决中,如下例子所示:spring-doc.cadn.net.cn

public class MyDecider implements JobExecutionDecider {
    public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
        String status;
        if (someCondition()) {
            status = "FAILED";
        }
        else {
            status = "COMPLETED";
        }
        return new FlowExecutionStatus(status);
    }
}

在下面的例子中,一个豆子实现了JobExecutionDecider通过 直接下一个使用 Java 配置时调用:spring-doc.cadn.net.cn

Java 配置
@Bean
public Job job(JobRepository jobRepository, MyDecider decider, Step step1, Step step2, Step step3) {
	return new JobBuilder("job", jobRepository)
			.start(step1)
			.next(decider).on("FAILED").to(step2)
			.from(decider).on("COMPLETED").to(step3)
			.end()
			.build();
}

在以下示例作业配置中,一个决定指定了要用的判定器 以及所有的过渡:spring-doc.cadn.net.cn

XML 配置
<job id="job">
    <step id="step1" parent="s1" next="decision" />

    <decision id="decision" decider="decider">
        <next on="FAILED" to="step2" />
        <next on="COMPLETED" to="step3" />
    </decision>

    <step id="step2" parent="s2" next="step3"/>
    <step id="step3" parent="s3" />
</job>

<beans:bean id="decider" class="com.MyDecider"/>

分流

到目前为止描述的每一个场景都涉及工作执行步骤一 时间线性地流淌。除了这种典型风格外,Spring Batch还允许 为配置一个作业并行流。spring-doc.cadn.net.cn

基于Java的配置允许你通过提供的构建器配置分割。作为 以下示例显示,分裂元素包含一个或多个元素,其中 可以定义完整的独立流程。一个分裂元素也可以包含以下任何 之前讨论过的过渡元素,例如:下一个属性或下一个,结束失败元素。spring-doc.cadn.net.cn

@Bean
public Flow flow1(Step step1, Step step2) {
	return new FlowBuilder<SimpleFlow>("flow1")
			.start(step1)
			.next(step2)
			.build();
}

@Bean
public Flow flow2(Step step3) {
	return new FlowBuilder<SimpleFlow>("flow2")
			.start(step3)
			.build();
}

@Bean
public Job job(JobRepository jobRepository, Flow flow1, Flow flow2, Step step4) {
	return new JobBuilder("job", jobRepository)
				.start(flow1)
				.split(new SimpleAsyncTaskExecutor())
				.add(flow2)
				.next(step4)
				.end()
				.build();
}

XML 命名空间允许你使用分裂元素。如下例子所示, 这分裂元素包含一个或多个元素,其中可以存在完整的独立流 被定义。一个分裂元素也可以包含上述任何过渡 元素,例如:下一个属性或下一个,结束失败元素。spring-doc.cadn.net.cn

<split id="split1" next="step4">
    <flow>
        <step id="step1" parent="s1" next="step2"/>
        <step id="step2" parent="s2"/>
    </flow>
    <flow>
        <step id="step3" parent="s3"/>
    </flow>
</split>
<step id="step4" parent="s4"/>

外部化流程定义和作业间依赖关系

作业中的一部分流程可以外部化为一个独立的 bean 定义,然后 重复使用。有两种方式。第一种是将流声明为 参考其他地方定义的。spring-doc.cadn.net.cn

以下 Java 示例展示了如何将一个流程声明为定义的流程的引用 别处:spring-doc.cadn.net.cn

Java 配置
@Bean
public Job job(JobRepository jobRepository, Flow flow1, Step step3) {
	return new JobBuilder("job", jobRepository)
				.start(flow1)
				.next(step3)
				.end()
				.build();
}

@Bean
public Flow flow1(Step step1, Step step2) {
	return new FlowBuilder<SimpleFlow>("flow1")
			.start(step1)
			.next(step2)
			.build();
}

以下 XML 示例展示了如何将一个流程声明为对定义的流程的引用 别处:spring-doc.cadn.net.cn

XML 配置
<job id="job">
    <flow id="job1.flow1" parent="flow1" next="step3"/>
    <step id="step3" parent="s3"/>
</job>

<flow id="flow1">
    <step id="step1" parent="s1" next="step2"/>
    <step id="step2" parent="s2"/>
</flow>

定义外部流的效果,如前例所示,是插入 从外部流到作业的步骤仿佛被内联声明。在 这样,许多作业可以引用相同的模板流程,并将这些模板组合成 不同的逻辑流。这也是区分集成测试的好方法 个体流动。spring-doc.cadn.net.cn

另一种外部化流的形式是使用工作步骤.一个工作步骤与 a 类似FlowStep但实际上是为 中的步骤创建并启动一个独立的作业执行 流程被指定。spring-doc.cadn.net.cn

以下示例展示了工作步骤在爪哇语中:spring-doc.cadn.net.cn

Java 配置
@Bean
public Job jobStepJob(JobRepository jobRepository, Step jobStepJobStep1) {
	return new JobBuilder("jobStepJob", jobRepository)
				.start(jobStepJobStep1)
				.build();
}

@Bean
public Step jobStepJobStep1(JobRepository jobRepository, JobLauncher jobLauncher, Job job, JobParametersExtractor jobParametersExtractor) {
	return new StepBuilder("jobStepJobStep1", jobRepository)
				.job(job)
				.launcher(jobLauncher)
				.parametersExtractor(jobParametersExtractor)
				.build();
}

@Bean
public Job job(JobRepository jobRepository) {
	return new JobBuilder("job", jobRepository)
				// ...
				.build();
}

@Bean
public DefaultJobParametersExtractor jobParametersExtractor() {
	DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor();

	extractor.setKeys(new String[]{"input.file"});

	return extractor;
}

以下示例是工作步骤以XML形式表示:spring-doc.cadn.net.cn

XML 配置
<job id="jobStepJob" restartable="true">
   <step id="jobStepJob.step1">
      <job ref="job" job-launcher="jobLauncher"
          job-parameters-extractor="jobParametersExtractor"/>
   </step>
</job>

<job id="job" restartable="true">...</job>

<bean id="jobParametersExtractor" class="org.spr...DefaultJobParametersExtractor">
   <property name="keys" value="input.file"/>
</bean>

作业参数提取器是一种决定执行上下文为 这转换为作业参数对于工作那就是跑步。这工作步骤是 当你想有更细致的监控和报告选项时,它很有用 工作和步骤。用工作步骤也常常是对“我该如何做”这个问题的好答案。 制造工作间的依赖关系?”这是将大型系统拆分成 模块更小,并控制工作流。spring-doc.cadn.net.cn