Spring Batch之读数据—FlatFileItemReader(二十五)

        FlatFileItemReader实现ItemReader接口,核心作用将Flat文件中的记录转换为Java对象。

一、FlatFileItemReader中关键属性

属性 类型 说明
bufferedReaderFactory BufferedReaderFactory 根据给定的resource创建BufferReader实例,默认使用DefaultBufferedReaderFactory创建文本类型的BufferReader实例。
comments String[] 定义注释行的前缀,当某行以这些字符串中的一个开头时候,此行记录将会被Spring Batch框架忽略。
encoding String 读取文件的编码类型,默认值为从环境变量file.encoding获取,如果没有设置则默认为UTF-8
lineMapper LineMapper 将一行文件记录转换为Java对象
linesToSkip int 读取文件的时候,定义跳过文件的行数;跳过的行记录将会被传递给skippedLinesCallback,执行跳过行的回调操作
recordSeparatorPolicy RecordSeparatorPolicy 定义文件如何区分记录,可以按照单行、也可以按照多行区分记录
resource Resource 需要读取的资源文件
skippedLinesCallback LineCallbackHandler 定义文件中记录跳过时执行的回调操作,通常与linesToSkip一起使用
strict boolean 定义读取文件不存在时候的策略,如果为true则抛出异常;如果为false表示不抛出异常,默认值为true

二、FlatFileItemReader中关键属性使用到的关键接口和类

关键类 说明
Resource 定义读取的文件资源
RecordSeparatorPolicy 从文件中确定一条记录的策略,记录可能是一行,可能是跨多行
LineMapper 将一条记录转化为Java数据对象,通常由LineTokenizer和FieldSetMapper组合来实现该功能
LineTokenizer 将一条记录分割为多个字段,在LineMapper的默认实现DefaultLineMapper中使用
FieldSetMapper 将多个字段值转化为Java对象,在LIneMapper的默认实现DefaultLineMapper中使用
LineCallbackHandler 处理文件中记录回调处理操作

关键接口和类与FlatFileItemReader中关键属性的关系如下:

Spring Batch之读数据—FlatFileItemReader(二十五)_第1张图片

 三、RecordSeparatorPolicy

        RecordSeparatorPolicy负责区分文件中不同记录的能力,即RecordSeparatorPolicy定义了如何从Flat文件中将不同的行记录区分开来作为一个完整的记录。

接口org.springframework.batch.item.file.separator.RecordSeparatorPolicy定义如下:

public interface RecordSeparatorPolicy {
    boolean isEndOfRecord(String var1);

    String postProcess(String var1);

    String preProcess(String var1);
}
  • isEndOfRecord():操作定义记录是否结束
  • preProcess():操作在一个新行加入到记录前触发
  • postProcess():操作在一个完整记录返回前触发

说明:FlatFileItemReader默认使用org.springframework.batch.item.file.separator.SimpleRecordSeparatorPolicy作为记录分割策略,即每一行作为一条记录。

四、LineMapper

        LineMapper接口定义了如何将Flat文件中的一条记录转化为域对象(通常为Java对象)。LineMapper接口仅有一个方法mapLine(),传入的参数是行的内容和行号,返回值为转换后的领域对象。LineMapper接口定义参数代码如下:

public interface LineMapper {
    T mapLine(String var1, int var2) throws Exception;
}

Spring Batch框架提供了4类默认的实现:

LineMapper 说明
DefaultLineMapper

默认的行转换类,引用接口LineToken和FieldSetMapper完成数据转换;LineTokenizer负责将一条记录转换为对象FieldSet(可以看作是一个key-value对的组合),FieldSetMapper负责将FieldSet转换为领域对象

org.springframework.batch.item.file.mapping.DefaultLineMapper

JsonLineMapper

负责将文件中JSON格式的文本数据转换为领域对象,转换后的领域对象格式为Map

org.springframework.batch.item.file.mapping.JsonLineMapper

PassThroughLineMapper

最简化的数据转换实现类,将一条记录直接返回,可以认为返回的领域对象为String类型的格式

org.springframework.batch.item.file.mapping.PassThroughLineMapper

PatternMatchingCompositeLineMapper

复杂数据转换类,可以为不同的记录定义不同的LineTokenizer和FieldSetMapper来实现数据转换;在执行过程中,根据每条记录的内容根据设置的条件找到匹配的LineTokenizer和FieldSetMapper进行数据转换;多用于处理同一文件中有不同类型记录的场景。可以认为PatternMatchingCompositeLineMapper组合了多个DefaultLineMapper

org.springframework.batch.item.file.mapping.PatternMatchingCompositeLineMapper

1.DefaultLineMapper

        org.springframework.batch.item.file.mapping.DefaultLineMapper是Spring Batch框架提供的一种LIneMapper实现,其默认使用LineTokenizer和FieldSetMapper完成数据转换功能。DefaultLineMapper通过组合的方式将任务委托给两个接口来完成,简化了DefaultLineMapper的代码结构,同时使得每个对象完成的任务职责非常简单,保持了代码结构清晰。

DefaultLineMapper、LineTokenizer、FieldSetMapper三者之间的关系:

Spring Batch之读数据—FlatFileItemReader(二十五)_第2张图片

  • LineTokenizer:负责将一条记录转换为FieldSet对象
  • FieldSetMapper:负责将FieldSet对象转换为领域对象

配置DefaultLineMapper的实例代码:

DefaultLineMapper" >
    lineTokenizer" ref="delimitedLineTokenizer" />
    fieldSetMapper" ref="creditBillFieldSetMapper"/>

(1)LineTokenizer

(1.1)介绍

        LineTokenizer接口负责将一条记录转换为FieldSet对象。接口仅有一个方法tokenizer(),传入的参数是行的内容,返回值为FieldSet对象。FieldSet对象中可以认为是一组key-value的组合,负责存放每条记录分割后的数据条目,条目以key-value(key可以认为是字段的名字name)的方式存在。

public interface LineTokenizer {
    FieldSet tokenize(String var1);
}

        FieldSet接口中定义了读取value值的基本类型操作,以及操作name相关的方法。在FieldSet中读取value时,支持直接转换为类型String、Boolean、Char、Byte、Short、Int、Long、Float、Double、BigDecimal、Date。

package org.springframework.batch.item.file.transform;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Properties;

public interface FieldSet {
    String[] getNames();

    boolean hasNames();

    String[] getValues();

    String readString(int var1);

    String readString(String var1);

    String readRawString(int var1);

    String readRawString(String var1);

    boolean readBoolean(int var1);

    boolean readBoolean(String var1);

    boolean readBoolean(int var1, String var2);

    boolean readBoolean(String var1, String var2);

    char readChar(int var1);

    char readChar(String var1);

    byte readByte(int var1);

    byte readByte(String var1);

    short readShort(int var1);

    short readShort(String var1);

    int readInt(int var1);

    int readInt(String var1);

    int readInt(int var1, int var2);

    int readInt(String var1, int var2);

    long readLong(int var1);

    long readLong(String var1);

    long readLong(int var1, long var2);

    long readLong(String var1, long var2);

    float readFloat(int var1);

    float readFloat(String var1);

    double readDouble(int var1);

    double readDouble(String var1);

    BigDecimal readBigDecimal(int var1);

    BigDecimal readBigDecimal(String var1);

    BigDecimal readBigDecimal(int var1, BigDecimal var2);

    BigDecimal readBigDecimal(String var1, BigDecimal var2);

    Date readDate(int var1);

    Date readDate(String var1);

    Date readDate(int var1, Date var2);

    Date readDate(String var1, Date var2);

    Date readDate(int var1, String var2);

    Date readDate(String var1, String var2);

    Date readDate(int var1, String var2, Date var3);

    Date readDate(String var1, String var2, Date var3);

    int getFieldCount();

    Properties getProperties();
}

(1.2)LineTokenizer系统实现

Spring Batch框架提供了4类默认的实现:

LineTokenizer 说明

DelimitedLineTokenizer

基于分隔符的行转换,根据给定的分隔符将一条记录转换为FieldSet对象org.springframework.batch.item.file.transform.DelimitedLineTokenizer

FixedLengthTokenizer 基于定长数据的行转换,根据给定的数据长度将一条记录转换为FieldSet对象org.springframework.batch.item.file.transform.FixedLengthTokenizer
RegexLineTokenizer 根据正则表达式的条件将一条记录转换为FieldSet对象org.springframework.batch.item.file.transform.RegexLineTokenizer
PatternMatchingCompositeLineTokenizer 可以为不同的记录定义不同的LineTokenizer;在执行过程中根据给定的标识与每条记录比对,如果满足则用指定的LineTokenizer;多用于处理同一文件中有不同类型记录的场场景org.springframework.batch.item.file.transform.PatternMatchingCompositeLineTokenizer

(1.3)LineTokenizer配置文件

        这里举例分隔符和定长类型的文件配置方法。

(1.3.1)分隔符文件配置(DelimitedLineTokenizer)

待处理的以“,”为分隔符的文件:

4047390012345678,tom,100.00,2013-2-2 12:00:08,Lu Jia Zui road 4047390012345678,tom,320.00,2013-2-3 10:35:21,Lu Jia Zui road 4047390012345678,tom,674.70,2013-2-6 16:26:49,South Linyi road 4047390012345678,tom,793.20,2013-2-9 15:15:37,Longyang road 4047390012345678,tom,360.00,2013-2-11 11:12:38,Longyang road 4047390012345678,tom,893.00,2013-2-28 20:34:19,Hunan road

配置分隔符DelimitedLineTokenizer:


    delimiter" value=","/>
    names">
        
            accountID
            name
            amount
            date
            address
        
    
  • delimiter:表示分隔符为“,”。
  • names:为每个字段定义名字,根据分隔符“,”获取的每个字段值分别对应names中定义的名字。

项目实例:

Spring Batch之读数据—读分隔符文件(二十六)_人……杰的博客-CSDN博客

(1.3.2)定长类型文件处理(FixedLengthTokenizer)

        如下是定长文件,每行记录长度一致,字段间不足的使用空格补齐,每个字段的固定长度为1-16,17-26,27-34,35-53,54-72:

4041390012345678tom       00100.002013-02-02 12:00:08    Lu Jia Zui road
4042390012345678tom       00320.002013-02-03 10:35:21    Lu Jia Zui road
4043390012345678jerry     00674.702013-02-06 16:26:49   South Linyi road
4044390012345678rose      00793.202013-02-09 15:15:37      Longyang road
4045390012345678bruce     00360.002013-02-11 11:12:38      Longyang road
4046390012345678rachle    00893.002013-02-28 20:34:19         Hunan road

 配置定长文件FixedLengthTokenizer:

        columns" value="1-16,17-26,27-34,35-53,54-72"/>

        names" value="accountID,name,amount,date,address"/>

  • columns:定义字段长度,字段顺序和names定义的名字匹配。
  • names:属性names为每个字段定义名字。

说明:定义字段长度时,从1开始,而不是从0开始。

项目实例:

Spring Batch之读数据—读定长文件(二十七)_人……杰的博客-CSDN博客

(2)FieldSetMapper

(2.1)介绍

        FieldSetMapper接口定义了如何将FieldSet对象转化为领域对象(通常为Java对象)。FieldSetMapper接口仅有一个方法mapFieldSet(),传入的参数是FieldSet对象,返回值为转换后的领域对象。接口如下:

public interface FieldSetMapper {
    T mapFieldSet(FieldSet var1) throws BindException;
}

(2.2)FieldSetMapper系统实现

Spring Batch框架中提供了3类默认的实现:

FieldSetMapper 说明
ArrayFieldSetMapper

将FieldSet对象转换为为String[]

org.springframework.batch.item.file.mapping.ArrayFieldSetMapper

BeanWrapperFieldSetMapper

将FieldSet对象根据名字映射到给定的Bean中,需要保证FieldSet中的name和Bean中属性的名称一致

org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper

PassThroughFieldSetMapper

直接返回FieldSet对象

org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper

(2.3)BeanWrapperFieldSetMapper

        BeanWrapperFieldSetMapper提供了一种方便的方式,将FieldSet对象根据名字直接映射成领域对象。如果声明使用BeanWrapperFieldSetMapper,只需要在属性prototypeBeanName中指明需要映射的领域对象即可,在运行期自动将FieldSet中name与领域对象同名的属性进行赋值操作。

配置信息:


    prototypeBeanName" value="creditBill" />

creditBill" scope="prototype"
           class="com.juxtapose.example.ch06.CreditBill">

其中CreditBill.java:

public class CreditBill implements Serializable{

   private static final long serialVersionUID = -4940717436114184875L;
   private String accountID = ""; /** 银行卡账户ID */
   private String name = "";     /** 持卡人姓名 */
   private double amount = 0;    /** 消费金额 */
   private String date;         /** 消费日期 ,格式YYYY-MM-DD HH:MM:SS*/
   private String address;          /** 消费场所 **/
}

项目实例:

Spring Batch之读数据—读定长文件(二十七)_人……杰的博客-CSDN博客

(2.4)自定义FieldSetMapper

        直接实现接口FieldSetMapper,可以实现自定义的转换器,下面就是自定义转换器CreditBillFieldSetMapper:

public class CreditBillFieldSetMapper implements FieldSetMapper {

	public CreditBill mapFieldSet(FieldSet fieldSet) throws BindException {
		CreditBill result = new CreditBill();
		result.setId(fieldSet.readString("id"));
		result.setAccountID(fieldSet.readString("accountID"));
		result.setName(fieldSet.readString("name"));
		result.setAmount(fieldSet.readDouble("amount"));
		result.setDate(fieldSet.readString("date"));
		result.setAddress(fieldSet.readString("address"));
		return result;
	}
}

        开发完毕自定义转换器CreditBillFieldSetMapper后,配置该类非常简单,只需要声明该类Bean即可:

    
    

项目实例:

Spring Batch之读数据—读分隔符文件(二十六)_人……杰的博客-CSDN博客

五、LineCallbackHandler

        在FlatFileItemReader中定义属性linesToSkip,表示从文件头开始跳过指定的行;当记录被跳过时,会触发接口LineCallbackHander中的handleLine()操作,该操作中能够获取跳过的行内容。

        经常使用的场景是将Falt文件中的文件头跳过后,直接写到目标文件的文件头中,这可以通过实现LineCallbcckHandler接口来完成。LineCallbackHandler接口定义如下:

public interface LineCallbackHandler {
    void handleLine(String var1);
}

说明:操作handleLine()在每次跳过时均会被触发

1.自定义实现LineCallbackHandler

实现接口LineCallbackHandler,将跳过的文件内容写入到目标文件中:

public class CopyHeaderLineCallbackHandler implements LineCallbackHandler,
		FlatFileHeaderCallback {
	private String header = "";

	public void handleLine(String line) {
		this.header = line;
	}

	public void writeHeader(Writer writer) throws IOException {
		writer.write(header);
	}
}
  • handleLine():负责收集读文件跳过的头记录
  • writeHeader():负责写入到目标文件中

其中,接口FlatFileHeaderCallback用于定义在ItemWrite之前写入特定的文件头,主要的操作是writeHeader().

配置信息:


    
    
    
    skippedLinesCallback" ref="copyHeaderLineCallbackHandler"/>
    .........

copyHeaderLineCallbackHandler"
    class="com.juxtapose.example.ch06.flat.CopyHeaderLineCallbackHandler">


    
    headerCallback" ref="copyHeaderLineCallbackHandler"/>
    .........

项目实例:

https://blog.csdn.net/qq_21370419/article/details/123417053

你可能感兴趣的:(Spring,Batch,spring,batch,java)