本文将通过一个完整的实例,与大家一起讨论运用Spring Batch对CSV文件的读写操作。此实例的流程是:读取一个含有四个字段的CSV文件(ID,Name,Age,Score),对读取的字段做简单的处理,然后输出到另外一个CSV文件中。
工程结构如下图:

JobLaunch类用来启动Job, CsvItemProcessor类用来对Reader取得的数据进行处理, Student类是一个POJO类,用来存放映射的数据。 inputFile.csv是数据读取文件, outputFile.csv是数据输出文件。
application.xml文件配置如前篇文章,不再赘述。
batch.xml文件中Job配置如下:
<job id="csvJob">
<step id="csvStep">
<tasklet transaction-manager="transactionManager">
<chunk reader="csvItemReader" writer="csvItemWriter" processor="csvItemProcessor" commit-interval="1">
</chunk>
</tasklet>
</step>
</job>
这个文件里配置了这次运行的JOB:csvJob。本Job包含一个Step,完成一个完整的CSV文件读写功能。分别由 csvItemReader完成CSV文件的读操作,由 csvItemProcessor完成对取得数据的处理,由 csvItemWriter完成对CSV文件的写操作。
batch.xml文件中csvItemReader配置如下:
<!-- 读取csv文件 -->
<bean:bean id="csvItemReader"
class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<bean:property name="resource" value="classpath:inputFile.csv"/>
<bean:property name="lineMapper">
<bean:bean
class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<bean:property name="lineTokenizer" ref="lineTokenizer"/>
<bean:property name="fieldSetMapper">
<bean:bean
class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<bean:property name="prototypeBeanName" value="student"></bean:property>
</bean:bean>
</bean:property>
</bean:bean>
</bean:property>
</bean:bean>
<bean:bean id="student" class="com.wanggc.springbatch.sample.csv.Student"></bean:bean>
<!-- lineTokenizer -->
<bean:bean id="lineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<bean:property name="delimiter" value=","/>
<bean:property name="names">
<bean:list>
<bean:value>ID</bean:value>
<bean:value>name</bean:value>
<bean:value>age</bean:value>
<bean:value>score</bean:value>
</bean:list>
</bean:property>
</bean:bean>
csvItemReader实现的是Spring Batch提供FlatFileItemReader类,此类主要用于Flat文件的读操作。它包含两个必要的属性 resource和 lineMapper。前者指定要读取的文件的位置,后者是将文件的每一行映射成一个Pojo对象。其中 lineMapper也有两个重要属性 lineTokenizer和 fieldSetMapper, lineTokenizer将文件的一行分解成一个 FieldSet,然后由 fieldSetMapper映射成Pojo对象。
这种方式与DB的读操作非常类似。lineMapper类似于ResultSet,文件中的一行类似于Table中的一条记录,被封装成的FieldSet,类似于RowMapper。至于怎么将一条记录封装,这个工作由lineTokenizer的继承类DelimitedLineTokenizer完成。DelimitedLineTokenizer的delimiter属性决定文件的一行数据按照什么分解,默认的是“,”, names属性标示分解的每个字段的名字,传给fieldSetMapper(本实例用的是BeanWrapperFieldSetMapper)的时候,就可以按照这个名字取得相应的值。fieldSetMapper的属性prototypeBeanName,是映射Pojo类的名字。设置了此属性后,框架就会将lineTokenizer分解成的一个FieldSet映射成Pojo对象,映射是按照名字来完成的(lineTokenizer分解时标注的名字与Pojo对象中字段的名字对应)。
总之,FlatFileItemReader读取一条记录由以下四步完成:1,从resource指定的文件中读取一条记录;2,lineTokenizer将这条记录按照delimiter分解成Fileset,每个字段的名字由names属性取得;3,将分解成的Fileset传递给fieldSetMapper,由其按照名字映射成Pojo对象;4,最终由FlatFileItemReader将映射成的Pojo对象返回,框架将返回的对象传递给Processor。
csvItemProcessor实现的是ItemProcessor类。此类接受Reader映射成的Pojo对象,可以对此对象做相应的业务逻辑处理,然后返回,框架就会将返回的结果传递给Writer进行写操作。具体实现代码如下:
package com.wanggc.springbatch.sample.csv;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.stereotype.Component;
/**
* ItemProcessor类。
*/
@Component("csvItemProcessor")
public class CsvItemProcessor implements ItemProcessor<Student, Student> {
/**
* 对取到的数据进行简单的处理。
*
* @param student
* 处理前的数据。
* @return 处理后的数据。
* @exception Exception
* 处理是发生的任何异常。
*/
@Override
public Student process(Student student) throws Exception {
/* 合并ID和名字 */
student.setName(student.getID() + "--" + student.getName());
/* 年龄加2 */
student.setAge(student.getAge() + 2);
/* 分数加10 */
student.setScore(student.getScore() + 10);
/* 将处理后的结果传递给writer */
return student;
}
}
batch.xml文件中csvItemReader配置如下:
<!-- 写CSV文件 -->
<bean:bean id="csvItemWriter"
class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
<bean:property name="resource" value="file:src/outputFile.csv"/>
<bean:property name="lineAggregator">
<bean:bean
class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<bean:property name="delimiter" value=","></bean:property>
<bean:property name="fieldExtractor">
<bean:bean
class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
<bean:property name="names" value="name,age,score"></bean:property>
</bean:bean>
</bean:property>
</bean:bean>
</bean:property>
</bean:bean>
csvItemWriter实现的是FlatFileItemWriter类。此类与FlatFileItemReader类相似,也有两个重要的属性:resource和lineAggregator。前者是要输出的文件的路径,后者和lineTokenizer类似。lineAggregator(本实例用DelimitedLineAggregator类)也有两个重要的属性:delimiter和fieldExtractor。Delimiter标示输出的字段以什么分割,后者将Pojo对象组装成由Pojo对象的字段组成的一个字符串。同样FlatFileItemWriter写一条记录也有以下四步完成:1,Processor传递过来一个对象给lineAggregator;2,lineAggregator将其这个对象转化成一个数组;3,再由lineAggregator的属性fieldExtractor将数组转化成按照delimiter分割一个字符串;4,将这个字符串输出。
这样,一条数据的读、处理、写操作就基本完成了。当然,读和写也可以自己写类来处理,只是要注意继承FlatFileItemReader和FlatFileItemWriter就可以了。
实例中用到的Student类代码如下:
package com.wanggc.springbatch.sample.csv;
/** Pojo类_Student */
public class Student {
/** ID */
private String ID = "";
/** 名字 */
private String name = "";
/** 年龄 */
private int age = 0;
/** 分数 */
private float score = 0;
/*getter 和setter已删除*/
}
实例中用到的输入数据如下:

实例输出结果如下:

本文的配置要注意以下两点:
1, 注意Writer的resource要写成“file:******”形式,不能用“classpath:******”形式。
2, 如果将Job配置中commit-interval属性配置为大于1时,每次commit的都是最后一条记录,前面读取的被覆盖了。具体原因不明,如果将Reader的fieldSetMapper属性自己重写,就可以解决这个问题。(注:student bean添加scope属性可以解决此问题:scope:"prototype".2011/12/16)
下次,将和大家一起讨论关于XML文件的读写问题。
相关推荐
本项目“Spring Batch Read csv”显然关注的是如何利用 Spring Batch 来读取 CSV 文件,这在数据处理和导入场景中非常常见。CSV(Comma Separated Values)是一种通用的、轻量级的文件格式,用于存储表格数据。 ...
SpringBatch提供了`FlatFileItemReader`和`FlatFileItemWriter`用于读写CSV文件。在案例中,你可以看到如何配置这些组件来解析逗号分隔的数据,并将其转换为Java对象,或者将Java对象写入CSV文件。通过设置字段映射...
总的来说,Spring Batch 提供了一套完整的框架来处理批量数据操作,它的灵活性和模块化设计使得我们可以方便地构建复杂的数据处理流程。在上述示例中,我们仅展示了最基础的用法,但实际应用中可以根据需要扩展更多...
Spring Batch是一个轻量级的,完全面向Spring的批处理框架,可以应用于企业级大量的数据处理系统。Spring Batch以POJO和大家熟知的Spring框架为基础,使开发者更容易的访问和利用企业级服务。Spring Batch可以提供...
在这个提供的压缩包文件中,名为"batch"的文件可能包含了一个简单的Spring Boot和Spring Batch整合的示例项目。这些文件可能包括Java源代码、配置文件以及可能的测试用例。通过查看这些文件,你可以学习如何将批处理...
Spring Batch提供了多种内置的ItemReader和ItemWriter实现,支持从数据库、文件等多种数据源读取数据,以及将数据写入到数据库、文件等目的地。 知识点五:数据处理 在数据被读取之后,通常需要经过一定的处理才能...
Spring Batch的事务管理是其核心特性之一。Spring Batch要求每个步骤都运行在一个事务上下文中。事务保证了步骤中进行的操作要么全部成功,要么全部回滚,这为批处理作业提供了数据一致性和完整性保障。 4. 错误...
Spring Batch可以通过配置文件或编程方式定义批处理作业的步骤和流程。 动态集群是指能够在运行时动态添加或移除服务器节点的集群环境。在Quartz中实现动态集群,主要是通过共享JobStore实现的,例如使用...
**四、Spring Batch 实战应用** 1. **数据迁移**: 使用 Spring Batch 实现大规模数据迁移,例如从旧数据库到新数据库的转换。 2. **报告生成**: 处理大量数据生成报表,如日志分析、财务报告等。 3. **定时任务**: ...
在 `springBatchDemo` 文件中,通常包含了示例代码,演示如何配置和运行一个简单的Spring Batch作业,涉及到读取数据库中的数据,进行处理,然后写回到数据库。你可以参考这些代码,理解Spring Batch的工作原理和...
6. **配置文件**:通常,这些配置会在Spring Batch的XML或Java配置文件中定义,包括Job、Step、Partitioner、TaskExecutor以及其他相关组件的设置。 在这个示例中,我们可能会看到如何通过XML或Java配置实现上述...
在`pom.xml`或`build.gradle`文件中添加依赖后,SpringBoot会自动加载SpringBatch的配置。 接着,SpringBatch的主要组件包括Job、Step、Tasklet、ItemReader、ItemWriter和ItemProcessor。Job是批处理任务的高层次...
csv-file-processor-spring-batch 该应用程序确实使用 Spring Batch 处理了一个巨大的 CSV 文件,它可以使用 Maven 进行构建/测试。 它确实需要传递以下属性/参数: --csv.processor.chunk.size={要处理的块大小} --...
在"SpringBatch的简单Sample"中,我们将探讨两种主要的处理模式:Tasklet和Chunk。 1. **Tasklet**: Tasklet 是SpringBatch中的基本执行单元,它可以被视为一个独立的任务。Tasklet 不是基于数据集的,而是执行一...
在压缩包文件 `spring-batch-4.0.0.M5` 中,包含了 Spring Batch 4.0.0 版本的预发布版本。这个版本可能包含了一些实验性的特性和改进,用于测试和反馈,以便在正式版中进行完善。 总的来说,Spring Batch 4.0.0 为...
SpringBatch 是一个强大的Java批处理框架,由Spring社区开发并维护,主要用于处理大量数据的后台操作,如批量导入导出、日志分析、定时任务等。在本文中,我们将深入探讨SpringBatch的学习入门,以及如何在IDEA环境...
- **批量导入/导出**:例如,从 CSV 文件中批量导入数据到数据库中,或将数据库中的数据批量导出为 Excel 文件。 - **数据分析与处理**:例如,对大量数据进行统计分析、汇总计算等操作。 - **后台任务调度**:如...
在这个名为 "Spring Batch sample project PatternMatchingCompositeLineMapper" 的示例项目中,我们聚焦于如何利用 `PatternMatchingCompositeLineMapper` 和 `MatchingClassLineAggregator` 这两个关键组件来优化...
Work with all aspects of batch processing in a modern Java environment using a selection of Spring frameworks. This book provides up-to-date examples using the latest configuration techniques based on...
### 基于Spring Batch的大数据量并行处理 #### 概述 Spring Batch是一款用于高效处理大量数据的开源框架,特别适用于批处理任务。它由Spring Source与Accenture合作开发,结合了双方在批处理架构和技术上的优势,...