Spring Batch Processor

时间:2015-08-10 23:26:15

标签: java spring spring-batch

我在Spring Batch中有一个要求,我有一个文件,其中有数千条记录按排序顺序排列。关键字段是产品代码。 该文件可能有多个相同产品代码的记录。要求是我必须对具有相同产品代码的记录进行分组 product集合中的代码(即List)然后将它们发送到一个方法,即validateProductCodes(List prodCodeList)。 我正在寻找最好的方法。我想到的方法是读取处理器中的每条记录,然后构建一个集合 处理器中相同产品代码的记录。如果处理器中的任何一点,如果记录中的产品代码不同,则意味着 productCode分组已完成,并且可以使用相同的产品代码为该组记录调用validateProductCodes()。我也使用Step.So 这不是自动意味着进程是多线程的吗?含义具有相同productCode的记录组将以多线程方式处理。请注意。

由于

1 个答案:

答案 0 :(得分:1)

您的问题中有两个问题:首先,您想知道如何将这些项目组合在一起以及如何处理这些项目。

为了对它们进行分组,您可以像Luca建议的那样创建一个组阅读器,或者类似:

public class GroupReader<I> implements ItemReader<List<I>>{
  private SingleItemPeekableItemReader<I> reader;
  private ItemReader<I> peekReaderDelegate;

  public void setReader(ItemReader<I> reader) {
      peekReaderDelegate = reader;
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    Assert.notNull(peekReaderDelegate, "The 'itemReader' may not be null");
    this.reader= new SingleItemPeekableItemReader<I>();
    this.reader.setDelegate(delegateReader);
  }

  @Override
  public List<I> read() throws Exception {
    State state = State.NEW;
    List<I> group = null;
    I item = null;

    while (state != State.COMPLETE) {
      item = reader.read();

      switch (state) {
        case NEW: {
          if (item == null) {
            // end reached
            state = State.COMPLETE;
            break;
          }

          group = new ArrayList<I>();
          group.add(item);
          state = State.READING;
          I nextItem = reader.peek();
          if (isItAKeyChange(item, nextItem)) {
            state = State.COMPLETE;
          }
          break;
        }
        case READING: {
          group.add(item);

          // peek and check if there the peeked entry has a new date
          I nextItem = peekEntry();
          if (isItAKeyChange(item, nextItem)) {
            state = State.COMPLETE;
          }
          break;
        }
        default: {
          throw new org.springframework.expression.ParseException(groupCounter, "ParsingError: Reader is in an invalid state");
        }
      }
    }

    return group;
  }
}

对于每个键,此阅读器将返回一个列表,其中包含与此键匹配的所有元素。因此,分组直接在读者中完成。 正如您所描述的那样,您无法使用处理器执行此操作。

关于多线程的第二个问题。 现在,使用步骤并不一定意味着,步骤是用多个线程处理的。

为此,您需要设置AsyncTaskExecutor,并且必须设置限制。

但是,如果你这样做,你的读者必须是线程安全的,否则你的分组不会起作用。你可以通过简单地将上面的read方法定义为synchronized来实现。

另一种方法是编写一个小的SynchronizedWrapperReader,如本问题所示:Parellel Processing Spring Batch StaxEventItemReader

请注意,根据您要写入的目标,您可能还需要同步编写器,并在必要时重新排序结果。