spring - 扩展ItemWriter Bean时如何在运行时使用@StepScope动态初始化ItemWriter Bean?
问题描述
[Spring Batch 的新手] 我有不同格式的不同 csv,将来可能会添加更多 csv 所以我想有一个通用的FlatFileItemReader<T>
而不是@Bean
为每个 csv 格式定义,我创建了一个基本配置类,然后为每个 csv 类型创建了具体类.
由于我已将 Reader bean 定义为,因此在批处理作业运行时它会使用包中的第一个具体类自动初始化 bean,此处@StepScope
讨论了相同类型的问题,但答案与我的情况无关
如何在作业运行期间将 ItemReader 的特定具体类类型传递给我的步骤?
这是我的基本配置类:
public abstract class AbstractBatchItemReader<T> {
private CsvInformation csvInformation;
protected AbstractBatchItemReader(CsvInformation csvInformation) {
this.csvInformation = csvInformation;
}
@Bean
@StepScope
//fileName is retrieved from jobParameters during runtime
public FlatFileItemReader<T> getItemReader(@Value("#{jobParameters['input.file.name']}") String fileName) {
return new FlatFileItemReaderBuilder<T>()
.name("invoiceHeaderItemReader")
.resource(new FileSystemResource(fileName))
.linesToSkip(1)
.delimited()
.names(csvInformation.getHeaders().split(","))
.fieldSetMapper(new BeanWrapperFieldSetMapper<T>() {{
setConversionService(new StringToLocalDateConversion().convert());
setTargetType(csvInformation.getERPClass());
}})
.build();
}
}
这是扩展基本配置的具体类:
@Configuration
public class InvoiceHeaderReader extends AbstractBatchItemReader<ERPInvoiceHeader> {
protected InvoiceHeaderReader(InvoiceHeaderCsvInformation csvInformation) {
super(csvInformation);
}
}
这是我的基本步骤配置:
public abstract class AbstractBatchStep<T> {
private final AbstractBatchItemReader<T> reader;
private final AbstractBatchItemWriter<T> writer;
private final StepBuilderFactory stepBuilderFactory;
protected AbstractBatchStep(AbstractBatchItemReader<T> reader,
AbstractBatchItemWriter<T> writer,
StepBuilderFactory stepBuilderFactory) {
this.reader = reader;
this.writer = writer;
this.stepBuilderFactory = stepBuilderFactory;
}
public Step getStep() {
afterPropertiesSet();
return stepBuilderFactory.get("Batch Step")
.<T, T>chunk(BatchConfiguration.READER_CHUNK_SIZE)
//fileName is passed during runtime
.reader(reader.getItemReader(null))
.writer(writer.getItemWriter())
.build();
}
}
这是扩展步骤配置的具体类:
@Configuration("invoice_header")
public class InvoiceHeaderStep extends AbstractBatchStep<ERPInvoiceHeader> {
protected InvoiceHeaderStep(InvoiceHeaderReader reader, InvoiceHeaderWriter writer, StepBuilderFactory stepBuilderFactory) {
super(reader, writer, stepBuilderFactory);
}
}
如果我尝试运行另一种类型的 csv,则整个作业循环仅针对包中的第一个具体类Unexpected token required n found n
运行到步骤
还请建议这种设计模式是否正确,可能有一种简单的方法来实现这一点。
解决方案
我想发布答案作为其他人的参考。
- 我创建了一个
AbstractBatchItemReader<T>
具有基本配置的类 - 扩展基本配置类的具体类
TypeOneCsvReader extends AbstractBatchItemReader<TypeOneEntity>
3.接口与Csv信息方法和类实现每种Csv类型的接口
这是代码示例:
AbstractBatchItemReader:
public abstract class AbstractBatchItemReader<T> {
private CsvInformation csvInformation;
protected AbstractBatchItemReader(CsvInformation csvInformation) {
this.csvInformation = csvInformation;
}
FlatFileItemReader<T> getItemReader() {
return new FlatFileItemReaderBuilder<T>()
.name("Batch Reader")
.resource(resource(null))
.linesToSkip(1)
.delimited()
.quoteCharacter(BatchConfiguration.READER_QUOTE_CHARACTER)
.names(csvInformation.getHeaders().split(","))
.fieldSetMapper(new BeanWrapperFieldSetMapper<T>() {{
setConversionService(StringToLocalDateConversion.convert());
setTargetType(csvInformation.getEntityClass());
}})
.build();
}
@Bean
@StepScope
public Resource resource(@Value("#{jobParameters['input.file.name']}") String fileName) {
return new FileSystemResource(fileName);
}
}
具体类:
@Configuration
public class TypeOneCsvReader extends AbstractBatchItemReader<TypeOneEntity> {
protected TypeOneCsvReader(TypeOneCsv csvInformation) {
super(csvInformation);
}
}
Csv信息接口:
public interface CsvInformation {
String getHeaders();
Class getEntityClass();
}
接口的每个实现都必须注解,@Component
以便具体阅读器类通过 DI 获取它
采用这种方法的好处是,它可以根据需要扩展到尽可能多的 csv 类型,并且 Reader 逻辑保留在一个位置
谢谢
推荐阅读
- java - 如何知道JVM当前是否在做GC?
- javascript - 在 Cucumber 中重用功能
- jquery - 如何使用 Jquery 屏蔽十进制输入?
- java - springboot 不会从 wsdl 生成类
- android - Xamarin Android,无法将 CG 桥设置为旧模式(MONO_GC_PARAMS=bridge-implementation)
- progress-bar - 如何在 vaadin 进度条中显示标签
- matlab - Matlab - 在逻辑数组中取第一个非零位置
- php - PHP - 当我在 isset() 中使用 $this 作为动态变量时,为什么不同版本的 PHP 返回不同的结果?
- php - 如何使用 gitlab ci 部署一个 php 网站
- ruby-on-rails - 使用输入销毁确认弹出窗口