繁体   English   中英

Spring Boot批处理-MultiResourceItemReader:错误时移至下一个文件

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM