作为Spring Batch的坚定倡导者,我一直在谈论Spring Batch的概念,它为开发人员提供了一个框架,使他们可以专注于解决业务需求。 这样,它使开发人员不必花费过多的时间来解决所有技术问题以支持该解决方案。
为了说明我的意思,我们将采用我之前编写的Spring Batch示例之一,并针对需要的其他业务需求进行一些增强。
新问题
在我的Spring Batch系列的第三部分中,我们介绍了一个处理大型Excel文件输出的教程。
后来确定另一个业务部门需要相同的数据,但是他们需要以管道分隔的文本文件格式(只有三个字段)输出数据。
有两种不同的方法可以执行此操作,但是在本示例中,我将向您展示如何快速实现自己的ItemStreamReader
,该项目将写作委派给各个作家。
我们需要做的第一件事是创建ItemStreamReader
的外壳。 我称之为MultiFormatItemWriter
。 这是外壳的样子:
package com.keyhole.example;import java.io.IOException;
import java.util.List;import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.AfterStep;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamWriter;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;import com.keyhole.example.poi.StockData;@Component("multFormatItemWriter")
@Scope("step")
public class MultiFormatItemWriter implements ItemStreamWriter<StockData> {@Overridepublic void write(List<? extends StockData> items) throws Exception {}@BeforeSteppublic void beforeStep(StepExecution stepExecution) {}@AfterSteppublic void afterStep(StepExecution stepExecution) throws IOException {}@Overridepublic void open(ExecutionContext executionContext) throws ItemStreamException {}@Overridepublic void update(ExecutionContext executionContext) throws ItemStreamException {}@Overridepublic void close() throws ItemStreamException {}}
接下来,我们需要对上一个示例中的现有StockDataExcelWriter
进行一些调整,以使其在新的MultiFormatItemWriter
作为委托工作。 我还发现,前面的示例存在一些与来自Nasdaq的数据流有关的问题。 其中一个字段的格式已更改,该示例不再起作用,因此必须先解决该问题,然后我们才能继续。
- 错误修复:将StockData上marketCap的字段类型从BigDecimal更改为String。 这些值现在在数据Feed中显示为“ $ 14.5M”和类似的值。
- 错误修复:由于数据格式已更改并且这些博客文章大多使用静态示例,因此我在src / test / resources下的
data.stock
包中创建了一个名为companylist.csv
的股票数据输入文件。 - 错误修复:修改了库存数据读取器以使用此数据文件代替实时的Nasdaq提要。
- 从
StockDataExcelWriter
删除了@Scope
(“步骤”)注释。 这是必需的,因为MultiFormatItemWriter
作用域是步骤级别。 - 从
StockDataExcelWriter
删除了@BeforeStep
和@AfterStep
批注,因为这些方法将直接从MultiFormatItemWriter中调用。 - 注释了将每个记录写入Excel文件300次的write方法内部的for循环。 这用于大型excel文件演示,因此需要还原该示例才能再次使用。
现在,我们已经解决了StockDataExcelWriter
,我们需要解决业务所需的其他格式输出。 第二个输出应该在管道分隔的文本文件中,并且仅包含符号,名称和最后销售字段。
对于这个委托作者,我们将使用FlatFileItemWriter
,它是Spring Batch提供的许多输出组件之一。 要使用它,这是一个非常简单的配置更改,看起来像这样:
<bean name="pipeDelimitedExtractFile" class="org.springframework.batch.item.file.FlatFileItemWriter"><property name="resource" value="file:/data/example/excel/extract-example.txt" /><property name="lineAggregator"><bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator"><property name="delimiter" value="|" /><property name="fieldExtractor"><bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor"><property name="names" value="symbol,name,lastSale" /></bean></property></bean></property>
</bean>
由于Spring Batch具有扎根于Spring框架的基础,因此可以轻松配置提供的FlatFileItemWriter
并将Bean连接到应用程序代码中。 在这种情况下,我们将使用提供的DelimitedLineAggregator
创建FlatFileItemWriter
,将管道字符指定为定界符,并将fieldExtractor
设置为使用BeanWrapperFieldExtractor
。
BeanWrapperFieldExtractor
获取发送到ItemStreamWriter
的StockData记录列表,并提取由逗号分隔的StockData bean中的字段名称列表指定的字段。 最后,指定用于输出的资源,在这种情况下为文件extract-example.txt,并将其写入/ data / example / excel目录。
现在,我们要做的就是将两个委托编写器连接到我们的MultiFormatItemWriter
。 确保在适当的方法中调用了委托编写器,然后完成! 这是MultiFormatITemWriter
的最终代码清单:
package com.keyhole.example;import java.io.IOException;
import java.util.List;import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.AfterStep;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamWriter;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;import com.keyhole.example.poi.StockData;
import com.keyhole.example.poi.StockDataExcelWriter;@Component("multFormatItemWriter")
@Scope("step")
public class MultiFormatItemWriter implements ItemStreamWriter<StockData> {@Autowiredprivate StockDataExcelWriter stockDataExcelWriter;@Autowired@Qualifier("pipeDelimitedExtractFile")private FlatFileItemWriter<StockData> extractWriter;@Overridepublic void write(List<? extends StockData> items) throws Exception {stockDataExcelWriter.write(items);extractWriter.write(items);}@BeforeSteppublic void beforeStep(StepExecution stepExecution) {stockDataExcelWriter.beforeStep(stepExecution);}@AfterSteppublic void afterStep(StepExecution stepExecution) throws IOException {stockDataExcelWriter.afterStep(stepExecution);}@Overridepublic void open(ExecutionContext executionContext) throws ItemStreamException {extractWriter.open(executionContext);}@Overridepublic void update(ExecutionContext executionContext) throws ItemStreamException {extractWriter.update(executionContext);}@Overridepublic void close() throws ItemStreamException {extractWriter.close();}}
如您所见,这里确实没有太多工作要做,这就是我想指出的。 我并没有真正显示出使用某些内置的读取器和写入器可以简单地实现某些业务解决方案。
最后的想法
现在我确实提到了解决此问题的几种方法。 第二个将利用Spring Batch随附的CompositeItemWriter
。 它所做的几乎和我在这里所做的完全相同,只是它获取了ItemWriters
的列表并在实现的每个方法中循环遍历它们。
在那种情况下,我将转换我的StockDataExcelWriter
来实现ItemStreamReader
接口,并且将用CompositeItemWriter
代替MultiFormatOutputWriter
,它将在作业配置xml中进行配置。 更少的代码。
因此,我今天在本文中的观点是表达如何使用Spring Batch提供的几个已经实现的组件轻松解决最常见的任务和业务解决方案。
这个示例和其他示例可以在GitHub的以下位置找到: https : //github.com/jonny-hackett/batch-example 。
翻译自: https://www.javacodegeeks.com/2016/08/spring-batch-multiple-format-output-writer.html