我有一个按照以下链接配置的弹簧批量应用程序。
https://spring.io/guides/gs/batch-processing/
现在我必须以这样一种方式配置步骤,如果用户输入是文件则必须采用FlatFileItemReader,如果输入是SQL,则必须使用JdbcPagingItemReader。我会将输入(文件/ sql)作为JobParameters传递。
根据我的理解,spring的上述示例中的所有内容都是单例bean,它们在应用程序启动时加载到ApplicationContext中。 由于步骤只能使用一个Reader配置一次。我如何配置它以根据用户输入采用不同的读者
如果只是读者正在改变,我不喜欢创造多个工作。
我想过使用Factory / Strategy模式但这只有在 Step 不是bean的情况下才能实现。这里所有这些都是在应用程序启动期间加载的bean。
无论模式如何,基于 JobParameters 在步骤中使用不同读者的解决方案都会有所帮助。
答案 0 :(得分:2)
你对豆子的看法是正确的。
如果您只有两种口味,最快的解决方案就是创建两个作业。但是,让我们忽视现实,谈论理论:
您可以创建两个步骤,每个步骤一个,并使用JobExecutionDecider
执行一个或另一个步骤(请参阅docs)。
或者您创建自己的ItemReader
并让它动态创建委托阅读器。如果您使用ItemStreamSupport
或AbstractItemCountingItemStreamItemReader
作为基类,则会获得open(ExecutionContext executionContext)
方法。
示例代码:
public class TicTacReader extends ItemStreamSupport implements ItemReader<TicTac>{
protected ItemReader<TypedFieldSet<RecordType>> delegate;
public TicTacReader() {
super();
setName(TicTacReader.class.getName());
}
@Override
public void open(ExecutionContext executionContext) throws ItemStreamException {
super.open(executionContext);
// TODO: use the appropriate reader
this.delegate = new VoodooReader();
}
@Override
public TicTac read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
TypedFieldSet<RecordType> line = this.delegate.read();
// TODO ...
}
}
答案 1 :(得分:1)
您可以使用@StepScope实现此目的。将您的bean名称,即FlatFileItemReader /或SQL放在作业参数中,然后使用下面的代码
示例实施
java配置方式
@StepScope
public Step step(@Value("#{jobParameters['beanId']}") final String beanId) {
return stepBuilderFactory.get("step")
.<POJO, POJO> chunk(10000)
.reader(getReader(beanId))
.processor(Processor)
.writer(Writer)
.build();
}
getReader(String beanId)
{
return applicationContext.getBean(beanId);
}
XML
<batch:chunk reader="#{jobParameters['beanId']}" writer="writer" processor="processor" commit-interval="100" />
答案 2 :(得分:0)
请记住,可以将Spring配置(因此,bean)设置为Spring概要文件,环境变量,应用程序上下文bean的存在,属性等。
因此,您应该能够根据执行上下文来过滤工厂(通过@Configuration类和@Bean方法)。