Spring integration 使用Spring集成和批处理读取CSV文件并将其插入数据库
我有一个监控FTP文件夹中特定csv文件的应用程序Spring integration 使用Spring集成和批处理读取CSV文件并将其插入数据库,spring-integration,spring-batch,Spring Integration,Spring Batch,我有一个监控FTP文件夹中特定csv文件的应用程序foo.csv,一旦找到该文件,它会将其拉到我的本地并生成一个新的输出格式bar.csv,然后应用程序会将新文件bar.csv发送回FTP文件夹,并将其从本地删除 现在,我想介绍一个进程,该进程将读取bar.csv,并将其插入数据库表中,然后再将其发送到FTP服务器 我假设这可以使用Spring批处理集成来完成,但我找不到如何做到这一点 下面是我的申请代码,供参考和建议 public IntegrationFlow localToFtpFlow(
foo.csv
,一旦找到该文件,它会将其拉到我的本地并生成一个新的输出格式bar.csv
,然后应用程序会将新文件bar.csv
发送回FTP文件夹,并将其从本地删除
现在,我想介绍一个进程,该进程将读取bar.csv
,并将其插入数据库表中,然后再将其发送到FTP服务器
我假设这可以使用Spring批处理集成来完成,但我找不到如何做到这一点
下面是我的申请代码,供参考和建议
public IntegrationFlow localToFtpFlow(Branch myBranch) {
return IntegrationFlows.from(Files.inboundAdapter(new File(myBranch.getBranchCode()))
.filter(new ChainFileListFilter<File>()
.addFilter(new RegexPatternFileListFilter("final" + myBranch.getBranchCode() + ".csv"))
.addFilter(new FileSystemPersistentAcceptOnceFileListFilter(metadataStore(dataSource), "foo"))),//FileSystemPersistentAcceptOnceFileListFilter
e -> e.poller(Pollers.fixedDelay(10_000)))
.enrichHeaders(h ->h.headerExpression("file_originalFile", "new java.io.File('"+ myBranch.getBranchCode() +"/FEFOexport" + myBranch.getBranchCode() + ".csv')",true))
.transform(p -> {
LOG.info("Sending file " + p + " to FTP branch " + myBranch.getBranchCode());
return p;
})
.log()
.transform(m -> {
this.defaultSessionFactoryLocator.addSessionFactory(myBranch.getBranchCode(),createNewFtpSessionFactory(myBranch));
LOG.info("Adding factory to delegation");
return m;
})
.publishSubscribeChannel(s ->
s.subscribe(f -> f.transform(fileMessageToJobRequest()).handle(jobLaunchingGateway()).channel("nullChannel"))
.subscribe(h -> h.handle(Ftp.outboundAdapter(createNewFtpSessionFactory(myBranch), FileExistsMode.REPLACE)
.useTemporaryFileName(true)
.autoCreateDirectory(false)
.remoteDirectory(myBranch.getFolderPath()), e -> e.advice(expressionAdvice()))))
/*.handle(Ftp.outboundAdapter(createNewFtpSessionFactory(myBranch), FileExistsMode.REPLACE)
.useTemporaryFileName(true)
.autoCreateDirectory(false)
.remoteDirectory(myBranch.getFolderPath()), e -> e.advice(expressionAdvice()))*/
.get();
}
@Bean
public FileMessageToJobRequest fileMessageToJobRequest(){
FileMessageToJobRequest fileMessageToJobRequest = new FileMessageToJobRequest();
fileMessageToJobRequest.setFileParameterName("input.file.name");
fileMessageToJobRequest.setJob(orderJob);
return fileMessageToJobRequest;
}
@Bean
public JobLaunchingGateway jobLaunchingGateway() {
SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
//simpleJobLauncher.setJobRepository(jobRepository);
simpleJobLauncher.setTaskExecutor(new SyncTaskExecutor());
JobLaunchingGateway jobLaunchingGateway = new JobLaunchingGateway(simpleJobLauncher);
return jobLaunchingGateway;
}
您需要考虑在<代码> IpgReTraseFuxs/Cuth>定义中使用<代码> PuxSudio BoeBohanChhanle()/Cyto>。将您的
.handle(Ftp.outboundAdapter())
作为一个订阅者放置(最好是第二个)。作为第一个,它应该类似于.handle(jobLaunchingGateway).channel(“nullChannel”)
您可以在Spring批处理中阅读关于JobLaunchingGateway
关键是,您希望将同一消息发送到多个地方。因此,PublishSubscribeChannel
是最好的方式:
我建议您将这些订阅者完全按照这个顺序排列,因为您确实希望在发送到FTP之前将其存储到DB中。如果没有执行器,第二个订户将等待第一个订户完成其工作
该.channel(“nullChannel”)
在那里是必需的,因为JobLaunchingGateway
实际上是一个网关,它返回一个jobsecution
作为应答。既然你对此不感兴趣,你只需要忽略它。当然,您可以在该网关之后使用另一个handle()
以某种方式处理此JobExecution
。关键是不要从第一个订阅者那里返回任何东西作为回复。它会以某种方式阻止你的主流
更新
我认为.transform(fileMessageToJobRequest())
必须在作业启动网关之前到达下面的第一个订户:
.publishSubscribeChannel(s ->
s.subscribe(f -> f.transform(fileMessageToJobRequest()).handle(jobLaunchingGateway()).channel("nullChannel"))
.subscribe(h -> h.handle(Ftp.outboundAdapter(createNewFtpSessionFactory(myBranch), ...))
关键是,您希望将相同的文件发送到下一个句柄()
,但在该转换器上游之后,它将被更改为JobLaunchRequest
,这对jobLaunchingGateway
有好处,但对Ftp.outboundAdapter()
没有好处
您的例外情况:
Caused by: java.lang.NullPointerException
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:98)
导致这段代码:Assert.notNull(jobParameters,“jobParameters不能为null”)代码>。因此,jobParametersBuilder.toJobParameters()
的计算结果为null
我帮不了你这么多自定义代码
更新2
嗯。看起来您的问题在JobLaunchingGateway
bean定义中。在那里,您可以显式地执行新的simplejoblancher()
,而无需作业存储库
注入
Spring Boot的BatchConfigureConfiguration
中似乎有一个BasicBatchConfigurer
,可以将它注入到这个JobLaunchingGateway
中。因此,我们将通过NPE。之后还有其他错误,但这已经是一个不同的故事了。 你需要考虑在<代码>整数流定义中使用<代码> PuxSudio BoeBohanChhanle()/Cyto>。将您的.handle(Ftp.outboundAdapter())
作为一个订阅者放置(最好是第二个)。作为第一个,它应该类似于.handle(jobLaunchingGateway).channel(“nullChannel”)
您可以在Spring批处理中阅读关于JobLaunchingGateway
关键是,您希望将同一消息发送到多个地方。因此,PublishSubscribeChannel
是最好的方式:
我建议您将这些订阅者完全按照这个顺序排列,因为您确实希望在发送到FTP之前将其存储到DB中。如果没有执行器,第二个订户将等待第一个订户完成其工作
该.channel(“nullChannel”)
在那里是必需的,因为JobLaunchingGateway
实际上是一个网关,它返回一个jobsecution
作为应答。既然你对此不感兴趣,你只需要忽略它。当然,您可以在该网关之后使用另一个handle()
以某种方式处理此JobExecution
。关键是不要从第一个订阅者那里返回任何东西作为回复。它会以某种方式阻止你的主流
更新
我认为.transform(fileMessageToJobRequest())
必须在作业启动网关之前到达下面的第一个订户:
.publishSubscribeChannel(s ->
s.subscribe(f -> f.transform(fileMessageToJobRequest()).handle(jobLaunchingGateway()).channel("nullChannel"))
.subscribe(h -> h.handle(Ftp.outboundAdapter(createNewFtpSessionFactory(myBranch), ...))
关键是,您希望将相同的文件发送到下一个句柄()
,但在该转换器上游之后,它将被更改为JobLaunchRequest
,这对jobLaunchingGateway
有好处,但对Ftp.outboundAdapter()
没有好处
您的例外情况:
Caused by: java.lang.NullPointerException
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:98)
导致这段代码:Assert.notNull(jobParameters,“jobParameters不能为null”)代码>。因此,jobParametersBuilder.toJobParameters()
的计算结果为null
我帮不了你这么多自定义代码
更新2
嗯。看起来您的问题在JobLaunchingGateway
bean定义中。在那里,您可以显式地执行新的simplejoblancher()
,而无需作业存储库
注入
Spring Boot的BatchConfigureConfiguration
中似乎有一个BasicBatchConfigurer
,可以将它注入到这个JobLaunchingGateway
中。因此,我们将通过NPE。之后还有其他错误,但这已经是另一回事了…谢谢Artem,我就快到了,我添加了所有需要的类和方法,但是getti