我们从数据库中读取大部分数据。有时结果集是空的,在这种情况下,我们希望工作立即停止,而不是交给作者。如果没有输入,我们不想创建文件。
目前我们通过一个返回特定字符串的 Step-Listener 来实现这一目标,该字符串是转换到下一个业务步骤或删除步骤的输入,删除我们之前创建的文件(该文件不包含实际数据)。
我希望在读者意识到没有输入之后结束这项工作?
我们从数据库中读取大部分数据。有时结果集是空的,在这种情况下,我们希望工作立即停止,而不是交给作者。如果没有输入,我们不想创建文件。
目前我们通过一个返回特定字符串的 Step-Listener 来实现这一目标,该字符串是转换到下一个业务步骤或删除步骤的输入,删除我们之前创建的文件(该文件不包含实际数据)。
我希望在读者意识到没有输入之后结束这项工作?
这种方法是在找不到文件时优雅地移动到下一步或结束批处理应用程序,并防止执行不需要的步骤(以及它们的侦听器)。
-> 检查 tasklet 中是否存在文件,例如FileValidatorTasklet
.
-> 当找不到文件时设置一些退出状态(枚举或最终字符串),这里我们设置了EXIT_CODE
示例小任务
public class FileValidatorTasklet implements Tasklet {
static final String EXIT_CODE = "SOME_EXIT_CODE";
static final String EXIT_DESC = "SOME_EXIT_DESC";
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
boolean isFileFound = false;
//do file check and set isFileFound
if(!isFileFound){
stepContribution.setExitStatus(new ExitStatus(EXIT_CODE, EXIT_DESC));
}
return RepeatStatus.FINISHED;
}
}
-> 在执行 FileValidatorTasklet 后,在此应用程序的作业配置中,检查是否存在EXIT_CODE
.
-> 如果找到代码,则提供此作业的后续路径,否则作业的正常流程。(这里我们只是在EXIT_CODE
找到时终止作业,否则继续下一步)
示例配置
public Job myJob(JobBuilderFactory jobs) {
return jobs.get("offersLoaderJob")
.start(fileValidatorStep).on(EXIT_CODE).end() // if EXIT_CODE is found , then end the job
.from(fileValidatorStep) // else continue the job from here, after this step
.next(step2)
.next(finalStep)
.end()
.build();
}
在这里,我们利用了 Spring Batch 中的条件步骤流。我们必须从步骤 A 定义两条独立的路径。流程类似于 A->B->C 或 A->D->E。
我经历过这个,因此我分享我的方法。最好是
throw new RunTimeException("msg");
.
它将开始终止 Spring Application ,而不是在此时完全终止。将调用(读取器/写入器)中的所有方法(如 close()),并调用所有 bean 的销毁方法。
注意:在 Listener 中执行此操作时,请记住,此时所有 bean 都已初始化,并且其初始化中的代码(如 afterPropertySet() )将已执行。
我认为上面是正确的方法,但如果你只愿意在那个时候终止,你可以试试
System.exit(1);
使用JobExecutionDecider并根据StepExecution的读取计数设置一个新的FlowExecutionStatus并将其路由到作业的末尾可能会更干净。
我和OP有同样的问题。我正在使用所有注释,并且如果在未找到任何结果(在我的情况下为文件)时读取器返回 null,则 Job bean 将无法使用 UnsatisfiedDependencyException 初始化,并且该异常被抛出到标准输出。
如果我创建一个阅读器,然后返回它并指定指定的文件,那么将创建作业。之后,一个 ItemStreamException 被抛出,但它被抛出到我的日志中,因为那时我已经通过了 Job 自动装配并在 Step 内。这似乎更可取,至少对于我正在做的事情。
任何其他解决方案将不胜感激。
Joshua 的回答是停止工作,而不是过渡到下一个业务步骤。
您的文件编写器可能仍会不必要地创建文件。您可以使用委托(FlatFileItemWriter)创建类似 LazyItemWriter 的东西,并且如果调用 write 方法,它只会调用 delegate.open(一次)。当然,您必须检查是否仅在先前打开委托时才需要调用 delegate.close()。这样可以确保不会创建空文件并且不再需要删除它。