spring-batch - 如何使用 Spring Batch 读取多行阅读器
问题描述
我想从固定格式的输入数据文件中读取数据,如下所示,每条记录包含多行,以 XYZ 开头是记录的开头,子序列行是 ABC 和 DEF 也是相同的记录。再次以 XYZ 开头是新记录,
我可以知道哪个最好使用 Spring 批处理 ItemReader 或 ItemStream 以及它会有所帮助的任何示例。提前谢谢
XYZ$19801234567S 2011234500001
ABC$II9J234565443
DEF$00095834753
XYZ$198003453S 212345300003
ABC$II43534503
DEF$00035345303
解决方案
当我们必须在一个文件中处理多种记录类型时,这是一种常见的情况。查看此处的文档https://docs.spring.io/spring-batch/docs/4.2.x/reference/html/readersAndWriters.html#prefixMatchingLineMapper。
在您的情况下,您可以为 ItemReader 定义一个映射器PatternMatchingCompositeLineMapper,您必须为每种情况定义不同的标记器。
例子:
@Bean
public PatternMatchingCompositeLineMapper patternMatchingLineMapper() {
PatternMatchingCompositeLineMapper lineMapper = new PatternMatchingCompositeLineMapper();
Map<String, LineTokenizer> tokenizers = new HashMap<>(3);
tokenizers.put("XYZ*", xyzTokenizer());
tokenizers.put("ABC*", abcTokenizer());
tokenizers.put("DEF*", defTokenizer());
lineMapper.setTokenizers(tokenizers);
Map<String, FieldSetMapper> mappers = new HashMap<>(2);
mappers.put("XYZ*", xyzFieldSetMapper());
mappers.put("ABC*", abcFieldSetMapper());
mappers.put("DEF*", defFieldSetMapper());
lineMapper.setFieldSetMappers(mappers);
return lineMapper;
}
您可以使用其他解决方案PatternMatchingCompositeLineTokenizer。在这种情况下,您可以按如下方式配置您的线路标记器:
@Bean
public LineTokenizer patternCompositeLineTokenizer() throws Exception {
FixedLengthTokenizer recordTypeXYZ = new FixedLengthTokenizer();
...
FixedLengthTokenizer recordTypeABC = new FixedLengthTokenizer();
...
FixedLengthTokenizer recordTypeDEF = new FixedLengthTokenizer();
...
Map<String, LineTokenizer> tokenizers = new HashMap(3);
tokenizers.put("XYZ*", recordTypeXYZ);
tokenizers.put("ABC*", recordTypeABC);
tokenizers.put("DEF*", recordTypeDEF);
PatternMatchingCompositeLineTokenizer lineTokenizer = new PatternMatchingCompositeLineTokenizer();
lineTokenizer.setTokenizers(tokenizers);
return lineTokenizer;
}
@Bean
public FieldSetMapper<YourDomain> fieldSetMapper() {
return fieldSet -> {
switch (fieldSet.readString("yourField")) {
case XYZ: return new XyzDomain(...);
case ABC: return new AbcDomain(...);
case DEF: return new DefDomain(...)
default: throw new IllegalArgumentException("Invalid record type ");
}
};
}
@Bean
@StepScope
public FlatFileItemReader<YourDomain> itemReader() throws Exception {
return new FlatFileItemReaderBuilder<YourDomain>()
.name("itemReader")
.resource(yourResource)
.lineTokenizer(patternCompositeLineTokenizer())
.fieldSetMapper(fieldSetMapper())
.build();
}
推荐阅读
- javascript - 如何循环数组以显示表中所有行的所有数据?
- angular - 如何通过 ng update 将 Angular 7 更新到 Angular 8
- java - 由于自定义约束验证器,验证器单元测试失败
- javascript - Ajax 不更新数据库中的属性
- java - 尝试通过反射访问内部类构造函数的参数注释时出现 ArrayIndexOutOfBoundsException
- tensorflow - 在其上应用 conv-pool 层后如何打印 tensorflow 对象的值?
- php - 如何通过 PHP 将 sql 字段中的扩展编号加载到 Select 选项元素中?
- c++ - 如何为类的每个实例创建实例特定的方法?
- angular - 将多个文档添加到集合中
- django - 当我点击提交按钮 django 时无法验证表单并刷新页面