Controlling Step Flow
有了将步骤组合在一起,并将它们与拥有作业的能力,就需要能够控制作业如何从一个步骤“流向”另一个步骤。Step
的故障并不一定意味着 Job
应该失败。此外,可能有多种类型的“success
”决定应该执行哪一个 Step
。取决于 Steps
组的配置方式,某些步骤甚至可能根本不会被处理。
With the ability to group steps together within an owning job comes the need to be able
to control how the job “flows” from one step to another. The failure of a Step
does not
necessarily mean that the Job
should fail. Furthermore, there may be more than one type
of “success” that determines which Step
should be executed next. Depending upon how a
group of Steps
is configured, certain steps may not even be processed at all.
.Step bean method proxying in flow definitions
一个步骤实例在流程定义中必须是唯一的。当一个步骤在流程定义中具有多个结果时,重要的是将步骤的相同实例传递给流程定义方法(start
、from
等)。否则,流程执行可能会表现得非常意外。
A step instance must be unique within a flow definition. When a step has multiple outcomes in a flow definition,
it is important that the same instance of the step is passed to the flow definition methods (start
, from
, etc).
Otherwise, the flow execution might behave unexpectedly.
在以下示例中,步骤被注入为流程或作业 bean 定义方法的参数。这种依赖项注入保证了流程定义中步骤的唯一性。但是,如果流程是通过调用带 @Bean
注释的步骤定义方法来定义的,那么如果禁用了 bean 方法代理(即 @Configuration(proxyBeanMethods = false)
),则步骤可能不是唯一的。如果首选 bean 间注入风格,则必须启用 bean 方法代理。
In the following examples, steps are injected as parameters to the flow or job bean definition methods. This dependency injection style guarantees the uniqueness of steps in the flow definition.
However, if the flow is defined by calling step definition methods annotated with @Bean
, then steps might not be unique if bean method proxying is disabled (ie @Configuration(proxyBeanMethods = false)
).
If the inter-bean injection style is preferred, then bean method proxying must be enabled.
请参阅 Using the @Configuration annotation部分以获取有关在 Spring 框架中进行 Bean 方法代理的更多详细信息。
Please refer to the Using the @Configuration annotation section for more details about bean method proxying in Spring Framework.
Sequential Flow
最简单的流程场景是其中所有步骤顺序执行的作业,如下所示:
The simplest flow scenario is a job where all of the steps execute sequentially, as the following image shows:
这可以通过在 step
中使用 next
来实现。
This can be achieved by using next
in a step
.
- Java
-
以下示例展示了如何在 Java 中使用
next()
方法:
The following example shows how to use the next()
method in 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
-
以下示例展示了如何在 XML 中使用
next
属性:
The following example shows how to use the next
attribute in 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
先运行,因为它是最先列出的 Step
。如果 stepA
正常完成,则 stepB
运行,依此类推。但是,如果 step A
失败,则整个 Job
失败,且 stepB
不会执行。
In the scenario above, stepA
runs first because it is the first Step
listed. If
stepA
completes normally, stepB
runs, and so on. However, if step A
fails,
the entire Job
fails and stepB
does not execute.
在 Spring Batch XML 命名空间中,在配置中列出的第一个步骤是_always_ 由 |
With the Spring Batch XML namespace, the first step listed in the configuration is
always the first step run by the |
Conditional Flow
在前一个示例中,只存在两种可能性:
In the preceding example, there are only two possibilities:
-
The
step
is successful, and the nextstep
should be executed. -
The
step
failed, and, thus, thejob
should fail.
在许多情况下,这可能就足够了。然而,对于一个场景又如何呢?在这种场景中,step
的故障应触发另一个 step
,而不是导致故障?下图展示了这样的一个流程:
In many cases, this may be sufficient. However, what about a scenario in which the
failure of a step
should trigger a different step
, rather than causing failure? The
following image shows such a flow:
- Java
-
Java API 提供了一组流畅的方法,让你能够指定流程以及在步骤失败时要做什么。以下示例展示了如何指定一个步骤 (
stepA
),然后根据stepA
是否成功进入两个不同的步骤 (stepB
或stepC
) 中的任意一个:
The Java API offers a fluent set of methods that let you specify the flow and what to do
when a step fails. The following example shows how to specify one step (stepA
) and then
proceed to either of two different steps (stepB
or stepC
), depending on whether
stepA
succeeds:
@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();
}
- XML
-
为了处理更复杂的场景,Spring Batch XML 命名空间让你能够在步骤元素中定义过渡元素。其中一个这样的过渡是
next
元素。像next
属性一样,next
元素会告诉Job
接下来的要执行哪个Step
。但是,与属性不同,允许在给定的Step
上使用任意数量的next
元素,並且在故障的情况下没有默认行为。这意味着,如果使用了过渡元素,则必须显式定义Step
过渡的所有行为。另请注意,单个步骤不能同时具有next
属性和transition
元素。
To handle more complex scenarios, the Spring Batch XML namespace lets you define transitions
elements within the step element. One such transition is the next
element. Like the next
attribute, the next
element tells the Job
which Step
to
execute next. However, unlike the attribute, any number of next
elements are allowed on
a given Step
, and there is no default behavior in the case of failure. This means that, if
transition elements are used, all of the behavior for the Step
transitions must be
defined explicitly. Note also that a single step cannot have both a next
attribute and
a transition
element.
next
元素指定了一个要匹配的模式以及要接下来执行的步骤,如下例所示:
The next
element specifies a pattern to match and the step to execute next, as
the following example shows:
<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
-
当使用 Java 配置时,
on()
方法使用一个简单的模式匹配方案来匹配Step
执行过程中产生的ExitStatus
。
When using java configuration, the on()
method uses a simple pattern-matching scheme to
match the ExitStatus
that results from the execution of the Step
.
- XML
-
当使用 XML 配置时,过渡元素的
on
属性使用一个简单的模式匹配方案来匹配Step
执行过程中产生的ExitStatus
。
When using XML configuration, the on
attribute of a transition element uses a simple
pattern-matching scheme to match the ExitStatus
that results from the execution of the
Step
.
模式中只允许两个特殊字符:
Only two special characters are allowed in the pattern:
-
*
matches zero or more characters -
?
matches exactly one character
例如,c*t
匹配 cat
和 count
,而 c?t
匹配 cat
但不匹配 count
。
For example, c*t
matches cat
and count
, while c?t
matches cat
but not count
.
虽然 Step
上的转换元素数量没有限制,但是,如果 Step
执行导致的 ExitStatus
并未被元素涵盖,那么框架将抛出异常,并且 Job
将失败。该框架会自动对转换按从最具体到最不具体进行排序。这意味着,即使在前面的示例中 stepA
的排序被交换,FAILED
的 ExitStatus
仍然会进入 stepC
。
While there is no limit to the number of transition elements on a Step
, if the Step
execution results in an ExitStatus
that is not covered by an element, the
framework throws an exception and the Job
fails. The framework automatically orders
transitions from most specific to least specific. This means that, even if the ordering
were swapped for stepA
in the preceding example, an ExitStatus
of FAILED
would still go
to stepC
.
Batch Status Versus Exit Status
为 Job
配置条件流程时,了解 BatchStatus
和 ExitStatus
之间的区别非常重要。BatchStatus
是一个枚举,既是 JobExecution
也是 StepExecution
的属性,并且由框架用于记录 Job
或 Step
的状态。它可以是以下值之一:COMPLETED
、STARTING
、STARTED
、STOPPING
、STOPPED
、FAILED
、ABANDONED
或 UNKNOWN
。其中多数是不言自明的:COMPLETED
是步骤或作业成功完成后设置的状态,FAILED
是失败后设置的状态,依此类推。
When configuring a Job
for conditional flow, it is important to understand the
difference between BatchStatus
and ExitStatus
. BatchStatus
is an enumeration that
is a property of both JobExecution
and StepExecution
and is used by the framework to
record the status of a Job
or Step
. It can be one of the following values:
COMPLETED
, STARTING
, STARTED
, STOPPING
, STOPPED
, FAILED
, ABANDONED
, or
UNKNOWN
. Most of them are self explanatory: COMPLETED
is the status set when a step
or job has completed successfully, FAILED
is set when it fails, and so on.
- Java
-
在使用 Java 配置时,以下示例包含
on
元素:
The following example contains the on
element when using Java Configuration:
...
.from(stepA).on("FAILED").to(stepB)
...
- XML
-
在使用 XML 配置时,以下示例包含
next
元素:
The following example contains the next
element when using XML configuration:
<next on="FAILED" to="stepB" />
乍一看,on
似乎引用了它所属 Step
的 BatchStatus
。但是,它实际上引用了 Step
的 ExitStatus
。顾名思义,ExitStatus
表示 Step
在完成执行后的状态。
At first glance, it would appear that on
references the BatchStatus
of the Step
to
which it belongs. However, it actually references the ExitStatus
of the Step
. As the
name implies, ExitStatus
represents the status of a Step
after it finishes execution.
- Java
-
在使用 Java 配置时,在前面的 Java 配置示例中显示的
on()
方法引用了ExitStatus
的退出代码。
When using Java configuration, the on()
method shown in the preceding
Java configuration example references the exit code of ExitStatus
.
- XML
-
更具体地说,在使用 XML 配置时,在前面的 XML 配置示例中显示的
next
元素引用了ExitStatus
的退出代码。
More specifically, when using XML configuration, the next
element shown in the
preceding XML configuration example references the exit code of ExitStatus
.
用英语说就是:“如果退出代码为 FAILED,则转到 stepB”。默认情况下,退出代码始终与 Step
的 BatchStatus
相同,这就是前面的条目有效的原因。但是,如果需要让退出代码不同怎么办?一个很好的例子是样本项目中的跳过样本作业:
In English, it says: “go to stepB if the exit code is FAILED”. By default, the exit
code is always the same as the BatchStatus
for the Step
, which is why the preceding entry
works. However, what if the exit code needs to be different? A good example comes from
the skip sample job within the samples project:
- Java
-
以下示例显示了如何在 Java 中使用不同的退出代码:
The following example shows how to work with a different exit code in 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
-
以下示例显示了如何在 XML 中使用不同的退出代码:
The following example shows how to work with a different exit code in XML:
<step id="step1" parent="s1">
<end on="FAILED" />
<next on="COMPLETED WITH SKIPS" to="errorPrint1" />
<next on="*" to="step2" />
</step>
step1
有三种可能:
step1
has three possibilities:
-
The
Step
failed, in which case the job should fail. -
The
Step
completed successfully. -
The
Step
completed successfully but with an exit code ofCOMPLETED WITH SKIPS
. In this case, a different step should be run to handle the errors.
前面的配置有效。但是,需要根据执行条件跳过记录来更改退出代码,如下面的示例所示:
The preceding configuration works. However, something needs to change the exit code based on the condition of the execution having skipped records, as the following example shows:
public class SkipCheckingListener extends StepExecutionListenerSupport {
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
,首先检查以确保 Step
成功,然后检查 StepExecution
中的跳过计数是否高于 0。如果满足这两个条件,则会返回一个新的具有退出代码 COMPLETED WITH SKIPS
的 ExitStatus
。
The preceding code is a StepExecutionListener
that first checks to make sure the Step
was
successful and then checks to see if the skip count on the StepExecution
is higher than
0. If both conditions are met, a new ExitStatus
with an exit code of
COMPLETED WITH SKIPS
is returned.
Configuring for Stop
在对 BatchStatus
and ExitStatus
进行讨论后,人们可能会好奇 `BatchStatus`和 `ExitStatus`如何针对 `Job`进行确定。虽然这些状态由执行的代码为 `Step`确定,但 `Job`的状态根据配置确定。
After the discussion of BatchStatus
and ExitStatus
,
one might wonder how the BatchStatus
and ExitStatus
are determined for the Job
.
While these statuses are determined for the Step
by the code that is executed, the
statuses for the Job
are determined based on the configuration.
到目前为止,所讨论的所有作业配置都至少有一个无转换的最终 Step
。
So far, all of the job configurations discussed have had at least one final Step
with
no transitions.
- Java
-
在以下 Java 示例中,在
step
执行后,Job
结束:
In the following Java example, after the step
executes, the Job
ends:
@Bean
public Job job(JobRepository jobRepository, Step step1) {
return new JobBuilder("job", jobRepository)
.start(step1)
.build();
}
- XML
-
在以下 XML 示例中,在
step
执行后,Job
结束:
In the following XML example, after the step
executes, the Job
ends:
<step id="step1" parent="s3"/>
如果未为 Step
定义转换,则 Job
的状态将按如下方式定义:
If no transitions are defined for a Step
, the status of the Job
is defined as
follows:
-
If the
Step
ends withExitStatus
ofFAILED
, theBatchStatus
andExitStatus
of theJob
are bothFAILED
. -
Otherwise, the
BatchStatus
andExitStatus
of theJob
are bothCOMPLETED
.
虽然这种终止批处理作业的方法对于某些批处理作业(例如简单的顺序步骤作业)来说已经足够,但可能需要自定义定义的作业停止情形。为此,Spring Batch 提供三个转换元素来停止 Job
(除了我们之前讨论的 xref:step/controlling-flow.adoc#nextElement[next
元素)。这些停止元素中的每一个都以特定 BatchStatus
停止 Job
。需要注意的是,停止转换元素对 Job
中任何 Steps
的 BatchStatus
或 ExitStatus
都没有影响。这些元素仅影响 Job
的最终状态。例如,作业中的每个步骤的状态都可能是 FAILED
,但作业的状态为 COMPLETED
。
While this method of terminating a batch job is sufficient for some batch jobs, such as a
simple sequential step job, custom defined job-stopping scenarios may be required. For
this purpose, Spring Batch provides three transition elements to stop a Job
(in
addition to the next
element that we discussed previously).
Each of these stopping elements stops a Job
with a particular BatchStatus
. It is
important to note that the stop transition elements have no effect on either the
BatchStatus
or ExitStatus
of any Steps
in the Job
. These elements affect only the
final statuses of the Job
. For example, it is possible for every step in a job to have
a status of FAILED
but for the job to have a status of COMPLETED
.
Ending at a Step
配置步骤结束会指导“作业”停止,其“批处理状态”为“完成”。已结束且状态为“完成”的“作业”无法重新启动(该框架会引发`JobInstanceAlreadyCompleteException`)。
Configuring a step end instructs a Job
to stop with a BatchStatus
of COMPLETED
. A
Job
that has finished with a status of COMPLETED
cannot be restarted (the framework throws
a JobInstanceAlreadyCompleteException
).
- Java
-
使用 Java 配置时,
end
方法用于该任务。end
方法还允许有一个可选的`exitStatus`参数,你可以用它来自定义“作业”的`ExitStatus`。如果未提供`exitStatus`值,那么为了与“批处理状态”匹配,ExitStatus`默认值为`COMPLETED(完成)
。
When using Java configuration, the end
method is used for this task. The end
method
also allows for an optional exitStatus
parameter that you can use to customize the
ExitStatus
of the Job
. If no exitStatus
value is provided, the ExitStatus
is
COMPLETED
by default, to match the BatchStatus
.
- XML
-
使用 XML 配置时,你可以使用`end`元素来执行该任务。
end`元素还允许有一个可选的`exit-code`属性,你可以用它来自定义“作业”的`ExitStatus
。如果未提供`exit-code`属性,那么为了与“批处理状态”匹配,ExitStatus`默认值为`COMPLETED(已完成)
。
When using XML configuration, you can use the end
element for this task. The end
element
also allows for an optional exit-code
attribute that you can use to customize the
ExitStatus
of the Job
. If no exit-code
attribute is given, the ExitStatus
is
COMPLETED
by default, to match the BatchStatus
.
考虑以下场景:如果`step2`失败,那么“作业”会停止,“批处理状态”为`COMPLETED(已完成),`ExitStatus`为`COMPLETED(已完成)
,而且`step3`不会运行。否则,执行会转到`step3`。注意,如果`step2`失败,那么“作业”不可重新启动(因为状态为`COMPLETED(完成)`)。
Consider the following scenario: If step2
fails, the Job
stops with a
BatchStatus
of COMPLETED
and an ExitStatus
of COMPLETED
, and step3
does not run.
Otherwise, execution moves to step3
. Note that if step2
fails, the Job
is not
restartable (because the status is COMPLETED
).
- Java
-
以下示例用 Java 展示了该场景:
The following example shows the scenario in Java:
@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
-
以下示例用 XML 展示了该场景:
The following example shows the scenario in XML:
<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">
Failing a Step
配置步骤在某个点失败会指导“作业”停止,其“批处理状态”为`FAILED(失败)`。与`end`不同,“作业”发生故障并不会阻止“作业”重新启动。
Configuring a step to fail at a given point instructs a Job
to stop with a
BatchStatus
of FAILED
. Unlike end, the failure of a Job
does not prevent the Job
from being restarted.
使用 XML 配置时,fail`元素还允许有一个可选的`exit-code`属性,该属性可用于自定义“作业”的`ExitStatus
。如果未提供`exit-code`属性,那么为了与“批处理状态”匹配,ExitStatus`默认值为`FAILED(失败)
。
When using XML configuration, the fail
element also allows for an optional exit-code
attribute that can be used to customize the ExitStatus
of the Job
. If no exit-code
attribute is given, the ExitStatus
is FAILED
by default, to match the
BatchStatus
.
考虑以下场景:如果`step2`失败,那么“作业”会停止,“批处理状态”为`FAILED(失败),`ExitStatus`为`EARLY TERMINATION(早期终止)
,而且`step3`不会执行。否则,执行会转到`step3`。此外,如果`step2`失败,而且“作业”重新启动,那么会在`step2`重新开始执行。
Consider the following scenario: If step2
fails, the Job
stops with a
BatchStatus
of FAILED
and an ExitStatus
of EARLY TERMINATION
and step3
does not
execute. Otherwise, execution moves to step3
. Additionally, if step2
fails and the
Job
is restarted, execution begins again on step2
.
- Java
-
以下示例用 Java 展示了该场景:
The following example shows the scenario in 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
-
以下示例用 XML 展示了该场景:
The following example shows the scenario in 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">
Stopping a Job at a Given Step
配置“作业”在特定步骤停止会指导“作业”停止,其“批处理状态”为`STOPPED(已停止)`。停止“作业”可以在处理过程中提供一个临时中断,以便操作者在重新启动“作业”前采取一些措施。
Configuring a job to stop at a particular step instructs a Job
to stop with a
BatchStatus
of STOPPED
. Stopping a Job
can provide a temporary break in processing,
so that the operator can take some action before restarting the Job
.
- Java
-
使用 Java 配置时,`stopAndRestart`方法需要一个`restart`属性,该属性指定“作业”重新启动后应该从哪个步骤开始执行。
When using Java configuration, the stopAndRestart
method requires a restart
attribute
that specifies the step where execution should pick up when the Job is restarted.
- XML
-
使用 XML 配置时,`stop`元素需要一个`restart`属性,该属性指定“作业”重新启动后应该从哪个步骤开始执行。
When using XML configuration, a stop
element requires a restart
attribute that specifies
the step where execution should pick up when the Job
is restarted.
考虑以下场景:如果`step1`完成的状态为`COMPLETE(已完成)`,那么“作业”随后会停止。在重新启动后,会从`step2`开始执行。
Consider the following scenario: If step1
finishes with COMPLETE
, the job then
stops. Once it is restarted, execution begins on step2
.
- Java
-
以下示例用 Java 展示了该场景:
The following example shows the scenario in Java:
@Bean
public Job job(JobRepository jobRepository, Step step1, Step step2) {
return new JobBuilder("job", jobRepository)
.start(step1).on("COMPLETED").stopAndRestart(step2)
.end()
.build();
}
- XML
-
以下清单用 XML 展示了该场景:
The following listing shows the scenario in XML:
<step id="step1" parent="s1">
<stop on="COMPLETED" restart="step2"/>
</step>
<step id="step2" parent="s2"/>
Programmatic Flow Decisions
在某些情况下,可能需要比`ExitStatus`更多信息才能决定接下来要执行哪个步骤。在这种情况下,可以使用`JobExecutionDecider`来协助决策,如下例所示:
In some situations, more information than the ExitStatus
may be required to decide
which step to execute next. In this case, a JobExecutionDecider
can be used to assist
in the decision, as the following example shows:
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);
}
}
- Java
-
在以下示例中,使用 Java 配置时,实现了`JobExecutionDecider`的 Bean 会直接传递到`next`调用中:
In the following example, a bean implementing the JobExecutionDecider
is passed
directly to the next
call when using Java configuration:
@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();
}
- XML
-
在以下作业配置示例中,`decision`指定要使用的决策模块以及所有转换:
In the following sample job configuration, a decision
specifies the decider to use as
well as all of the transitions:
<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"/>
Split Flows
到目前为止描述的每一种情况都涉及一个“作业”,该“作业”以线性方式一次执行一个步骤。除了这种典型风格外,Spring Batch 还允许使用并行流来配置“作业”。
Every scenario described so far has involved a Job
that executes its steps one at a
time in a linear fashion. In addition to this typical style, Spring Batch also allows
for a job to be configured with parallel flows.
- Java
-
基于 Java 的配置允许你通过提供的构建器配置拆分。如下例所示,
split`元素包含一个或多个`flow`元素,可以在其中定义完全独立的流。`split`元素还可以包含前面讨论过的任何转换元素,如`next`属性或`next
、`end`或`fail`元素。
Java-based configuration lets you configure splits through the provided builders. As the
following example shows, the split
element contains one or more flow
elements, where
entire separate flows can be defined. A split
element can also contain any of the
previously discussed transition elements, such as the next
attribute or the next
,
end
, or fail
elements.
@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
-
XML 命名空间允许你使用`split`元素。如下例所示,
split`元素包含一个或多个`flow`元素,可以在其中定义完全独立的流。`split`元素还可以包含前面讨论过的任何转换元素,如`next`属性或`next
、`end`或`fail`元素。
The XML namespace lets you use the split
element. As the following example shows,
the split
element contains one or more flow
elements, where entire separate flows can
be defined. A split
element can also contain any of the previously discussed transition
elements, such as the next
attribute or the next
, end
, or fail
elements.
<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"/>
Externalizing Flow Definitions and Dependencies Between Jobs
作业中的部分流程可以被声明为一个单独的 bean 定义,然后被重用。有两种方法可以做到这一点。首先是声明流程为对其他地方定义的流程引用。
Part of the flow in a job can be externalized as a separate bean definition and then re-used. There are two ways to do so. The first is to declare the flow as a reference to one defined elsewhere.
- Java
-
以下 Java 示例显示如何声明流程为对其他地方定义的流程的引用:
The following Java example shows how to declare a flow as a reference to a flow defined elsewhere:
@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
-
以下 XML 示例显示如何声明流程为对其他地方定义的流程的引用:
The following XML example shows how to declare a flow as a reference to a flow defined elsewhere:
<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>
如前例所示,定义一个外部流程的效果是将外部流程中的步骤插入作业中,就好像它们已内联声明一样。通过这种方式,很多作业都可以引用相同的模板流程,并将这样的模板组合成不同的逻辑流程。这还是分离单个流程的集成测试的一种好方法。
The effect of defining an external flow, as shown in the preceding example, is to insert the steps from the external flow into the job as if they had been declared inline. In this way, many jobs can refer to the same template flow and compose such templates into different logical flows. This is also a good way to separate the integration testing of the individual flows.
外部流程的另一种形式是使用 JobStep
。JobStep
类似于 FlowStep
,但实际上会创建并启动一个单独的作业执行,用于在指定流程中的步骤。
The other form of an externalized flow is to use a JobStep
. A JobStep
is similar to a
FlowStep
but actually creates and launches a separate job execution for the steps in
the flow specified.
- Java
-
以下示例显示了 Java 中
JobStep
的示例:
The following example shows an example of a JobStep
in 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
-
以下示例显示了 XML 中
JobStep
的示例:
The following example hows an example of a JobStep
in 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>
作业参数提取器是一种策略,它确定如何将 Step
的 ExecutionContext
转换为运行中的 Job
的 JobParameters
。当您想要对作业和步骤进行更精细的选项监控和报告时,JobStep
会很有用。使用 JobStep
通常也是回答“如何在作业之间创建依赖关系?”这一问题的不错答案。它是一种将大型系统分解为更小的模块并控制作业流的好方法。
The job parameters extractor is a strategy that determines how the ExecutionContext
for
the Step
is converted into JobParameters
for the Job
that is run. The JobStep
is
useful when you want to have some more granular options for monitoring and reporting on
jobs and steps. Using JobStep
is also often a good answer to the question: “How do I
create dependencies between jobs?” It is a good way to break up a large system into
smaller modules and control the flow of jobs.