从 spring 批次的当前步骤调用上一步

Calling previous step from the current step in the spring batch

我需要使用 Spring 默认 FlatFileReader 读取我们的模块相关事务之一 table 来获取记录并使用 Spring FlatFileWriter 来写入,所以我没有控制权关于这些 reader 和作家,因为它们不是定制的。 然后第二步是 tasklet 使用 SFTP 将相同的平面文件传输到远程位置。

但有时当 Spring FlatFile reader 没有得到记录时,它会生成带有 header 的空文件。

所以我在第二步 tasklet 中检查文件的内容并检查它是否包含 header 并记录然后在该步骤中传输相同的内容否则我将插入一些默认记录保存一些交易逻辑 table。插入完成后,我想从当前的 tasklet 步骤调用上一步,即步骤 1 Spring 平面文件 reader。

请让我知道如何从当前步骤调用上一步,即 tasklet。

请找到以下示例作业配置

    <batch:step id="FlatFileStep3" next="TransmissionFlatFileStep4">
    <batch:tasklet>
        <batch:chunk reader="FlatFileReader" writer="FlatFileWriter" commit-interval="50"/> 
    </batch:tasklet>
                   </batch:step>
<batch:step id="TransmissionFlatFileStep4">
    <batch:tasklet>
        <batch:chunk ref="TransmissionFlatFileTasklet"/>    
        <batch:next on="NOT_COMPLETED" to="FlatFileStep3"/>
        <batch:next on="COMPLETED" to="UpdateTxnTableStep5"/>
    </batch:tasklet>
</batch:step>
<batch:step id="UpdateTxnTableStep5">
    <batch:tasklet>
        <batch:chunk ref="UpdateTxnTableTasklet"/>  
    </batch:tasklet>
</batch:step>

当 spring 批处理到达 TransmissionFlatFileStep4 时,然后在 TransmissionFlatFileTasklet 中我有逻辑来检查文件内容。如果文件为空,那么我有插入逻辑将一些默认数据插入到我们的事务 table。然后在同一个 tasklet (TransmissionFlatFileTasklet) 中,我通过实现 StepExecutionListener 接口覆盖 public ExitStatus afterStep(StepExecution stepExecution) 方法并设置自定义退出状态 NOT_COMPLETED & COMPLETED 所以它在状态为 COMPLETED 时调用 UpdateTxnTableStep5 并在 NOT_COMPLETED 上调用 FlatFileCreationStep3 所以这次将使用这些默认记录生成平面文件但是一旦平面文件完成它应该再次调用 TransmissionFlatFileStep4 这没有发生批次抛出错误:无法找到下一个状态

您是否考虑过使用 5.3 部分中记录的控制流。有了它,你就可以定义一个退出代码,它可以代表你什么时候想回调到第一步,然后在第一步上有一个类似的东西,它可以控制是再次通过整个过程还是结束。

举个例子说明我的想法:

<job id="job">
<step id="firstStep" parent="parent1">
    <next on="*" to="secondStep" />
    <end on="GOTOEND" />
</step>
<step id="secondStep" parent="parent2" next="thirdStep" />
<step id="thirdStep" parent="parent3" >
    <next on="RESEND" to="firstStep" />
    <end on="*" />
</step>

您可以切换它,但是您想要管理步骤的退出状态。

从那里您可以通过步骤侦听器控制步骤的退出状态,该侦听器可以检查步骤上下文中的一些瞬态数据集。

另一种选择可能是使用决策者来选择去哪里。我没有亲自使用过这些,但根据它们可能对你有用的文档。

除了 ,这里还有一些实施技巧。

要控制 tasklet 的 return 代码(即 "next" 标签中的值 "on="),例如可以实现 StepExecutionListener(或添加实现此 class 的自定义侦听器)。然后在方法afterStep中,你可以使用自己的逻辑来return一个自定义的exitCode:

@Override
public ExitStatus afterStep(StepExecution stepExecution) {

    if (true) // Your logic
        return new ExitStatus("GOTOEND"); // Your custom code
    else
        return null; // Inherit status from step
}

关于 Decider 的更多信息:这些位于步骤之间的作业定义中,并使用您自己的逻辑来确定下一步。它们的工作方式与 afterStep 相同:

<batch:decision decider="myDecider" id="myDecider">
    <batch:end on="GOTOEND" />
    <batch:next on="OTHER" to="OtherStep"/>
    <batch:fail on="*" />
</batch:decision>

<bean id="myDecider" class="xx.xx.xx.MyDecider"></bean>

bean引用的class需要实现JobExecutionDecider并覆盖方法decide:

@Override
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {

    if (true) // Your logic 
        return new FlowExecutionStatus("GOTOEND");
    else
        return FlowExecutionStatus.FAILED;

}

此外,如果您需要控制 FlatFileItemWriter 的内容,可以将 属性 shouldDeleteIfEmpty 设置为 false 以防止文件被正在创建。参见 FlatFileItemWriter documentation