![](/img/trans.png)
[英]Spring Batch: MultiResourceItemReader with custom ItemReader reads the same file ad infinitum
[英]Spring Boot batch - MultiResourceItemReader : move to next file on error
在批处理服务中,我使用MultiResourceItemReader读取了多个XML文件,该文件委托给StaxEventItemReader。
如果在读取文件时出现错误(例如解析异常),我想指定给Spring开始读取下一个匹配的文件。 例如,使用@OnReadError注释和/或SkipPolicy。
当前,当出现读取异常时,该批处理将停止。
有人知道怎么做吗?
编辑:我看到MultiResourceItemReader有一个方法readNextItem(),但它是私有的-_-
我有一段时间没有使用SB了,但是我想看一下MultiResourceItemReader
代码,我想您可以编写自己的ResourceAwareItemReaderItemStream
包装器,在其中检查设置为移至下一个文件或使用委托执行标准读取的标志。
该标志可以存储在执行上下文中或包装中,并且应在下一步移动后清除。
class MoveNextReader<T> implements ResourceAwareItemReaderItemStream<T> {
private ResourceAwareItemReaderItemStream delegate;
private boolean skipThisFile = false;
public void setSkipThisFile(boolean value) {
skipThisFile = value;
}
public void setResource(Resource resource) {
skipThisFile = false;
delegate.setResource(resource);
}
public T read() {
if(skipThisFile) {
skipThisFile = false;
// This force MultiResourceItemReader to move to next resource
return null;
}
return delegate.read();
}
}
使用此类作为MultiResourceItemReader
委托,并在@OnReadError
注入MoveNextReader
并设置MoveNextReader.skipThisFile
。
我无法自己测试代码,但我希望这可以成为一个好的起点。
这是我的最后一个类,用于读取多个XML文件并在一个文件发生读取错误时跳转到下一个文件(这要归功于Luca的想法)。
我的自定义ItemReader,从MultiResourceItemReader扩展:
public class MyItemReader extends MultiResourceItemReader<InputElement> {
private SkippableResourceItemReader<InputElement> reader;
public MyItemReader() throws IOException {
super();
// Resources
PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
this.setResources( resourceResolver.getResources( "classpath:input/inputFile*.xml" ) );
// Delegate reader
reader = new SkippableResourceItemReader<InputElement>();
StaxEventItemReader<InputElement> delegateReader = new StaxEventItemReader<InputElement>();
delegateReader.setFragmentRootElementName("inputElement");
Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
unmarshaller.setClassesToBeBound( InputElement.class );
delegateReader.setUnmarshaller( unmarshaller );
reader.setDelegate( delegateReader );
this.setDelegate( reader );
}
[...]
@OnReadError
public void onReadError( Exception exception ){
reader.setSkipResource( true );
}
}
中间的ItemReader用于跳过当前资源:
public class SkippableResourceItemReader<T> implements ResourceAwareItemReaderItemStream<T> {
private ResourceAwareItemReaderItemStream<T> delegate;
private boolean skipResource = false;
@Override
public void close() throws ItemStreamException {
delegate.close();
}
@Override
public T read() throws UnexpectedInputException, ParseException, NonTransientResourceException, Exception {
if( skipResource ){
skipResource = false;
return null;
}
return delegate.read();
}
@Override
public void setResource( Resource resource ) {
skipResource = false;
delegate.setResource( resource );
}
@Override
public void open( ExecutionContext executionContext ) throws ItemStreamException {
delegate.open( executionContext );
}
@Override
public void update( ExecutionContext executionContext ) throws ItemStreamException {
delegate.update( executionContext );
}
public void setDelegate(ResourceAwareItemReaderItemStream<T> delegate) {
this.delegate = delegate;
}
public void setSkipResource( boolean skipResource ) {
this.skipResource = skipResource;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.