如何 运行 read() 函数只执行一次 Spring 批处理
How to run read() function only once Spring Batch
我正在创建一个 Spring 批处理作业 xml:
<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" />
这是我的 reader class:
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;
}
但是 reader class 继续 运行ning。我如何停在第一个运行?
我也试过这个:
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;
}
read() 函数进入循环..
引用 ItemReader.read()
Javadoc:
Reads a piece of input data and advance to the next one. Implementations must return null
at the end of the input data set.
因此,您需要在第一次阅读后 return null
向 Spring 批次表明没有更多内容可读。
您可以像这样使用 ListIteamReader
(示例,未测试):
public class StockReader extends ListItemReader<StockData> {
public StockReader(String URL) {
super(createListFromUrl(URL));
}
public List<StockData> createListFromUrl(String URL) {
// create your ArrayList<StockData> list from URL
}
}
这个简单的委托封装了一次性阅读。
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;
}
}
您可以创建自己的 reader 而无需考虑一次性阅读,并使用这个小委托将其包装。
您的股票URL读者可以定义为
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;
}
}
创建 OneTimeReader
并将 StockURLReader
设置为委托,这样您就可以将 StockData 读取与一次性读取逻辑分开。
如果您想读取一组 StockData
,最好的解决方案是创建一个 StockDataListBean
,您可以在其中存储从拆分的 URL.
中读取的所有 StockData
class StockDataListBean {
List<StockData> data = new LinkedList<StockData>();
}
并将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;
}
}
我正在创建一个 Spring 批处理作业 xml:
<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" />
这是我的 reader class:
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;
}
但是 reader class 继续 运行ning。我如何停在第一个运行?
我也试过这个:
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;
}
read() 函数进入循环..
引用 ItemReader.read()
Javadoc:
Reads a piece of input data and advance to the next one. Implementations must return
null
at the end of the input data set.
因此,您需要在第一次阅读后 return null
向 Spring 批次表明没有更多内容可读。
您可以像这样使用 ListIteamReader
(示例,未测试):
public class StockReader extends ListItemReader<StockData> {
public StockReader(String URL) {
super(createListFromUrl(URL));
}
public List<StockData> createListFromUrl(String URL) {
// create your ArrayList<StockData> list from URL
}
}
这个简单的委托封装了一次性阅读。
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;
}
}
您可以创建自己的 reader 而无需考虑一次性阅读,并使用这个小委托将其包装。
您的股票URL读者可以定义为
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;
}
}
创建 OneTimeReader
并将 StockURLReader
设置为委托,这样您就可以将 StockData 读取与一次性读取逻辑分开。
如果您想读取一组 StockData
,最好的解决方案是创建一个 StockDataListBean
,您可以在其中存储从拆分的 URL.
StockData
class StockDataListBean {
List<StockData> data = new LinkedList<StockData>();
}
并将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;
}
}