如何在Spring Batch中只运行一次read()函数

Ama*_*man 6 java spring spring-batch spring-xd

我正在使用以下xml创建一个Spring Batch作业:

<batch:job id="simulatorJob" restartable="false">
    <batch:step id="step1">
        <batch:tasklet transaction-manager="transactionManager">
            <batch:chunk reader="stockListner" writer="customWriter"
                commit-interval="5">
            </batch:chunk>
        </batch:tasklet>
    </batch:step>
</batch:job>

<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />

<bean id="stockListner" class="com.XXX.stock.java.StockReader" scope="step">
    <property name="URL" value="NTPC,TCS" />
    <!-- <property name="URL" value="NTPC" /> -->
    <!-- <property name="URL" value="TCS" /> -->
</bean>

<bean id="customWriter" class="com.XXX.stock.java.FlatFileWriter" />
Run Code Online (Sandbox Code Playgroud)

这是我的读者课程:

private String URL;

public String getURL() {
    return URL;
}

public void setURL(String uRL) {
    URL = uRL;
}

public ArrayList<StockData> read() throws Exception, UnexpectedInputException,ParseException, NonTransientResourceException {
    ArrayList<StockData> list = new ArrayList<StockData>();
    String[] splitStocks = URL.split(",");      

    for(int i=0; i < splitStocks.length;i++){
        list.add(stockReader.getStockData(splitStocks[i]));     
    }
    return list;        
}  
Run Code Online (Sandbox Code Playgroud)

但读者班继续运行.我怎么在第一次运行时停止?

我试过这个:

public StockData read() throws Exception, UnexpectedInputException,ParseException, NonTransientResourceException {
    ArrayList<StockData> list = new ArrayList<StockData>();
    String[] splitStocks = URL.split(",");

    for(int i=0; i < splitStocks.length;i++)
    {  
           return stockReader.getStockData(splitStocks[i]);
    }

    return null;
}  
Run Code Online (Sandbox Code Playgroud)

read()函数进入循环..

Tun*_*aki 5

引用ItemReader.read()Javadoc:

读取一段输入数据并前进到下一条。实现必须null在输入数据集的末尾返回。

因此,您需要null在第一次读取后返回,以向 Spring Batch 表明没有更多内容可读取。


Luc*_*cci 4

这个简单的委托封装了一次性读取。

class OneItemReader<T> implements ItemReader<T> {
  boolean read = false;
  ItemReader<T> delegate;

  @Override
  public T read() {
    if(read) {
      return null;
    }
    T item = delegate.read();
    read = true;
    return item;
  }
}
Run Code Online (Sandbox Code Playgroud)

您可以创建自己的阅读器,而无需考虑一次性阅读并使用这个小委托来包装它。

您的 StockURLReader 可能定义为

class StockURLReader implements ItemReader<StockReader> {
  String[] tokens = new String[0];
  int index = 0;
  StockDAO stockReader;

  void setURL(String URL) {
    this.tokens = URL.split(",");
    index = 0;
  }

  StockData read() {
    if(index < tokens.length) {
      return stockReader.getStockData(tokens[index++]);
    }
    return null;
  }
}
Run Code Online (Sandbox Code Playgroud)

创建OneTimeReader并设置StockURLReader为委托,您可以将 StockData 读取与一次性读取逻辑分开。
如果您想读取一组StockData内容,最好的解决方案是创建一个StockDataListBean存储StockData从拆分 URL 读取的所有内容的位置。

class StockDataListBean {
  List<StockData> data = new LinkedList<StockData>();
}
Run Code Online (Sandbox Code Playgroud)

并修改StockURLReader为:

class StockURLReader implements ItemReader<StockDataListBean> {
  String[] URLs = new String[0];
  int index;
  StockDAO stockReader;

  void setURLs(String[] URL) {
    this.URLs = URL;
    index = 0;
  }

  StockDataListBean read() {
    StockDataListBean item = null;
    if(index < URLs.length)
    {
      item = new StockDataListBean();
      for(String token : URLs[index].split(",").length)
      {
        item.data.add(stockReader.getStockData(token));
      }
    }
    return item;
  }
}
Run Code Online (Sandbox Code Playgroud)