我想知道如何在ItemWriter
中确定Spring Batch当前处于块处理模式还是回退单项处理模式。首先,我没有找到有关该后备机制如何实现的信息。
即使我还没有找到解决我实际问题的解决方案,我也想与您分享我关于后备机制的知识。
如果我错过了任何事情,请随时添加其他信息的答案;-)
最佳答案
可以在FaultTolerantChunkProcessor和RetryTemplate中找到跳过机制的实现。
假设您配置了skippable exceptions,但没有配置retryable exceptions。并且当前块中有一个失败的项目导致异常。
现在,首先将整个块写入。在处理器的write()
方法中,您可以看到RetryTemplate
被调用。它还获得了对RetryCallback
和RecoveryCallback
的两个引用。
切换到RetryTemplate
。查找以下方法:
protected <T> T doExecute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback, RetryState state)
在那里,您可以看到
RetryTemplate
只要没有用尽即可重试(即在我们的配置中恰好一次)。这样的重试将由可重试的异常引起。不可重试的异常将在此处立即中止重试机制。重试用尽或中止后,
RecoveryCallback
将被调用:e = handleRetryExhausted(recoveryCallback, context, state);
这就是现在开始单项处理模式的地方!
RecoveryCallback(在处理器的
write()
方法中定义!)将锁定输入块(inputs.setBusy(true)
)并运行其scan()
方法。在那里,您可以看到从块中取出了一个项目:List<O> items = Collections.singletonList(outputIterator.next());
如果
ItemWriter
可以正确处理此单个项目,则该块将完成,并且ChunkOrientedTasklet
将运行另一个块(用于下一个单个项目)。这将导致对RetryCallback
的常规调用,但是由于该块已被RecoveryTemplate
锁定,因此会立即调用scan()
方法:if (!inputs.isBusy()) {
// ...
}
else {
scan(contribution, inputs, outputs, chunkMonitor);
}
因此,将处理另一个单个项目并将其重复进行,直到原始块逐个项目已被处理:
if (outputs.isEmpty()) {
inputs.setBusy(false);
就是这样。希望对您有所帮助。而且,我甚至更希望您可以通过搜索引擎轻松找到它,而不会浪费太多时间,自己找到它。 ;-)