Spring 批处理 FlatFileItemReader 令牌错误
Spring batch FlatFileItemReader token error
我的文件系统中有两个 csv 文件,我需要根据某些请求类型使用 spring 批处理。
请求类型的文件:EOD(没有 headers)
12345,BBG
23232,BBG
请求类型的另一个文件:ANCIENT(没有 headers)
12345,BBG,20201115
23232,BBG,20201115
两个文件都有前两个必填字段,id
和 source
。 ANCIENT 文件可以选择包含第 3 和第 4 字段 startDate
和 endDate
如何创建对两个文件都适用的 FlatFileItemReader
?目前我有类似的东西:
我的 ItemReader 实现读取 csv 文件:
@Bean
@Scope(value = "step", proxyMode = ScopedProxyMode.INTERFACES)
public FlatFileItemReader<FixingDTO> fileReader(@Value("#{jobExecutionContext['type']}") String type) {
SomeType type = forName(type);
return new FlatFileItemReaderBuilder<MyDTO>()
.name("fileReader")
.resource(new ClassPathResource(MAP.get(type)))
.delimited()
.delimiter(",")
.names("id", "source", "startDate", "endDate")
.fieldSetMapper(myDTOMapper())
.build();
}
字段的映射器:
public class MyDTOFieldMapper implements FieldSetMapper<MyDTO> {
@Override
public MyDTO mapFieldSet(FieldSet fieldSet) throws BindException {
MyDTO dto = new MyDTO();
dto.setId(fieldSet.readString("id"));
dto.setSource(fieldSet.readString("source"));
dto.setStartDate(formatDate(fieldSet.readString("startDate")));
dto.setEndDate(formatDate(fieldSet.readString("endDate")));
return dto;
}
private LocalDate formatDate(String dateString) {
return LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd"));
}
}
当 运行 作业时,我得到一个令牌异常:
Caused by: org.springframework.batch.item.file.transform.IncorrectTokenCountException: Incorrect number of tokens found in record: expected 4 actual 2
我想简单地处理行中的任何内容并分配给 object 变量。 StartDate 和 endDate 可以为空。
DelimitedLineTokenizer
中有字段 strict
(默认值:true),属性 正是您要查找的内容。您应该将该字段设置为 false。
行为描述:
/**
* Public setter for the strict flag. If true (the default) then number of
* tokens in line must match the number of tokens defined
* (by {@link Range}, columns, etc.) in {@link LineTokenizer}.
* If false then lines with less tokens will be tolerated and padded with
* empty columns, and lines with more tokens will
* simply be truncated.
*
* @param strict the strict flag to set
*/
public void setStrict(boolean strict) {
this.strict = strict;
}
不幸的是,在构建器中没有设置严格字段的好方法,否则我们可以通过以下方式设置:
@Bean
@Scope(value = "step", proxyMode = ScopedProxyMode.INTERFACES)
public FlatFileItemReader<FixingDTO> fileReader(@Value("#{jobExecutionContext['type']}") String type) {
SomeType type = forName(type);
return new FlatFileItemReaderBuilder<MyDTO>()
.name("fileReader")
.fieldSetMapper(myDTOMapper())
.lineTokenizer(new DelimitedLineTokenizer() {
{
setDelimiter(",");
setNames("id", "source", "startDate", "endDate");
setStrict(false);
}
})
.build();
}
我的文件系统中有两个 csv 文件,我需要根据某些请求类型使用 spring 批处理。
请求类型的文件:EOD(没有 headers)
12345,BBG
23232,BBG
请求类型的另一个文件:ANCIENT(没有 headers)
12345,BBG,20201115
23232,BBG,20201115
两个文件都有前两个必填字段,id
和 source
。 ANCIENT 文件可以选择包含第 3 和第 4 字段 startDate
和 endDate
如何创建对两个文件都适用的 FlatFileItemReader
?目前我有类似的东西:
我的 ItemReader 实现读取 csv 文件:
@Bean
@Scope(value = "step", proxyMode = ScopedProxyMode.INTERFACES)
public FlatFileItemReader<FixingDTO> fileReader(@Value("#{jobExecutionContext['type']}") String type) {
SomeType type = forName(type);
return new FlatFileItemReaderBuilder<MyDTO>()
.name("fileReader")
.resource(new ClassPathResource(MAP.get(type)))
.delimited()
.delimiter(",")
.names("id", "source", "startDate", "endDate")
.fieldSetMapper(myDTOMapper())
.build();
}
字段的映射器:
public class MyDTOFieldMapper implements FieldSetMapper<MyDTO> {
@Override
public MyDTO mapFieldSet(FieldSet fieldSet) throws BindException {
MyDTO dto = new MyDTO();
dto.setId(fieldSet.readString("id"));
dto.setSource(fieldSet.readString("source"));
dto.setStartDate(formatDate(fieldSet.readString("startDate")));
dto.setEndDate(formatDate(fieldSet.readString("endDate")));
return dto;
}
private LocalDate formatDate(String dateString) {
return LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd"));
}
}
当 运行 作业时,我得到一个令牌异常:
Caused by: org.springframework.batch.item.file.transform.IncorrectTokenCountException: Incorrect number of tokens found in record: expected 4 actual 2
我想简单地处理行中的任何内容并分配给 object 变量。 StartDate 和 endDate 可以为空。
DelimitedLineTokenizer
中有字段 strict
(默认值:true),属性 正是您要查找的内容。您应该将该字段设置为 false。
行为描述:
/**
* Public setter for the strict flag. If true (the default) then number of
* tokens in line must match the number of tokens defined
* (by {@link Range}, columns, etc.) in {@link LineTokenizer}.
* If false then lines with less tokens will be tolerated and padded with
* empty columns, and lines with more tokens will
* simply be truncated.
*
* @param strict the strict flag to set
*/
public void setStrict(boolean strict) {
this.strict = strict;
}
不幸的是,在构建器中没有设置严格字段的好方法,否则我们可以通过以下方式设置:
@Bean
@Scope(value = "step", proxyMode = ScopedProxyMode.INTERFACES)
public FlatFileItemReader<FixingDTO> fileReader(@Value("#{jobExecutionContext['type']}") String type) {
SomeType type = forName(type);
return new FlatFileItemReaderBuilder<MyDTO>()
.name("fileReader")
.fieldSetMapper(myDTOMapper())
.lineTokenizer(new DelimitedLineTokenizer() {
{
setDelimiter(",");
setNames("id", "source", "startDate", "endDate");
setStrict(false);
}
})
.build();
}