該系列課程中的示例代碼使用springBatch版本為3.0.7;講解可能會講一些4.0.X的特性
示例代碼位址: https://git.oschina.net/huicode/springbatch-learn
在這裡說到FlatFile的時候,其實XML,CSV,TXT三種檔案格式中XML是不屬于FlatFile 的,XML在Batch中是屬于StaxEvent,但是本章主要講述SpringBatch對于檔案的讀寫,是以放到一起說明。
本文主要講解通過SpringBatch來處理文本格式的檔案,在實際的業務中也許文本檔案轉DB data或者DB data轉文本檔案的情形更多。
說明:在spring官方文檔中的說明都是基于xml配置的方式來實作ItemReader、ItemWriter、Job、Step的配置的,為了符合springBoot的配置方式,示例代碼都是配置代碼實作的。
使用springBatch對于 xml 檔案進行讀寫 操作時需要引入spring-oxm 包
https://blog.didispace.com/spring-batch-2/#pom-xml%E9%85%8D%E7%BD%AE pom.xml配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
項目結構說明
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CNxETMmdTOkZjNmlDMxYWY0QDO0AjNxUWOjJmY4QjMh9CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)
為了更好的管理代碼,根據類對應的職責建立了不同的包:
- launcher: 執行,調用job
- processor: 負責資料的轉換與處理
https://blog.didispace.com/spring-batch-2/#%E6%96%87%E4%BB%B6%E8%AF%BB%E5%86%99 檔案讀寫
使用 FlatFileItemReader,FlatFileItemWriter 幫我們做了什麼?
- FlatFileItem 能夠以固定長度進行讀寫(對于大檔案尤為重要),開發者不用關注檔案的讀寫流問題
- 對檔案讀寫時能夠保證事物
詳解 FlatFileItemReader
FlatFileItemReader 是對檔案讀取的類,一般是對表格資料,或者文本檔案資料的處理。該類的以下兩個屬性是必須要set的
- setResource 指定檔案資源的位置:通過ClassPathResource(類所在路徑)或者FileSystemResource(檔案系統所在路徑)來指定要讀取的檔案
- setLineMapper 行映射:指定行與實體對象之間的映射關系,示例代碼使用了DefaultLineMapper
- seEncoding 讀取編碼格式,預設為
iso-8859-1
- setStrict 嚴格模式,輸入檔案不存在會抛出異常,阻斷目前job,預設為true
@Bean
public FlatFileItemReader<Person> csvItemReader() {
FlatFileItemReader<Person> csvItemReader = new FlatFileItemReader<>();
csvItemReader.setResource(new ClassPathResource("data/sample-data.csv"));
csvItemReader.setLineMapper(new DefaultLineMapper<Person>() {{
setLineTokenizer(new DelimitedLineTokenizer() {{
setNames(new String[]{"name", "age"});
}});
setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
setTargetType(Person.class);
}});
}});
return csvItemReader;
}
詳解 FlatFileItemWriter
FlatFileItemWriter 是對檔案的寫入類,将批量資料流寫入檔案,該類使用必須了解下面幾個方法的用法:
- setLineAggregator 和 FlatFileItemReader 的setLineMapper方法有着相似之處,setLineAggregator方法是将對象屬性聚合為字元串,聚合時根據需要設定分隔符(setDelimiter),以及對象屬性對應的字元名稱(setFieldExtractor)
-
- LineAggregator 接口是建立對象屬性聚合字元串
- ExtractorLineAggregator 是抽象類實作LineAggregator接口。使用 FieldExtractor将對象屬性轉換為數組,該類的擴充類負責将數組轉換字元串(doAggregate)
-
-
- DelimitedLineAggregator 繼承 ExtractorLineAggregator。是一種更常使用的聚合方式、将數組用指定符号分割,預設使用逗号
- FormatterLineAggregator 繼承 ExtractorLineAggregator。對數組字元串的最大長度,最小長度的校驗,以及格式化操作
-
-
- PassThroughLineAggregator 實作LineAggregator接口,是一種簡單的聚合方式使用對象的.toString()傳回值,作為聚合字元串
- RecursiveCollectionLineAggregator 實作LineAggregator接口,将Collection 集合周遊,集合的聚合通過系統行分割符分割,對象字段的聚合使用LineAggregator接口對應的聚合方法是可選擇的。
- setResource 是指定輸出檔案的位置,同樣也是必須的,示例代碼中使用了new ClassPathResource(“/data/sample-data.txt”) 實際開發中更多的是 new FilePathResource()
- setEncoding 設定編碼,預設也是 iso-8859-1
@Bean
public FlatFileItemWriter<Person> txtItemWriter() {
FlatFileItemWriter<Person> txtItemWriter = new FlatFileItemWriter<>();
txtItemWriter.setAppendAllowed(true);
txtItemWriter.setEncoding("UTF-8");
txtItemWriter.setResource(new ClassPathResource("/data/sample-data.txt"));
txtItemWriter.setLineAggregator(new DelimitedLineAggregator<Person>() {{
setDelimiter(",");
setFieldExtractor(new BeanWrapperFieldExtractor<Person>() {{
setNames(new String[]{"name", "age"});
}});
}});
return txtItemWriter;
}
XML檔案處理
對xml檔案的處理需要引入spring-oxm包,僅對xml的輸出進行詳解,XML讀取類似
對xml寫入操作的對象為StaxEventItemWriter,與FlatFileItemWriter的使用類似,StaxEventItemWriter 與 FlatFileItemWriter都有着setResource方法,StaxEventItemWriter預設編碼為utf-8
- setRootTagName 設定根節點标簽名稱
- setMarshaller 指定對象與節點 映射關系
https://blog.didispace.com/spring-batch-2/#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%A4%84%E7%90%86%E5%99%A8ItemProcessor 自定義處理器ItemProcessor
ItemProcessor主要負責資料的轉換與處理,将讀取到的檔案 轉換為輸出檔案的對象,是以temProcessor<Person, Person>這裡不一定都是Person,實作process方法,實作資料的轉換與處理。
public class PersonItemProcessor implements ItemProcessor<Person, Person> {
@Override
public Person process(Person person) throws Exception {
person.setAge(person.getAge() + 1);
person.setName(person.getName() + "-_-");
return person;
}
}
整個Job 的處理流程
- 讀取csv檔案
- 資料處理,轉換
- 輸出txt檔案
- 讀取txt檔案
- 輸出XML檔案