Spring集成在聚合后调用另一个处理程序方法
我正在开发一个系统,它将读取和处理目录中的文件。处理完所有文件后,它将调用一个方法,该方法将生成一个文件。此外,它应该根据文件名路由/处理文件,我也使用了spring集成路由器。下面是集成的代码片段。我的问题是,如果我删除任何一行Spring集成在聚合后调用另一个处理程序方法,spring,spring-boot,spring-integration,Spring,Spring Boot,Spring Integration,我正在开发一个系统,它将读取和处理目录中的文件。处理完所有文件后,它将调用一个方法,该方法将生成一个文件。此外,它应该根据文件名路由/处理文件,我也使用了spring集成路由器。下面是集成的代码片段。我的问题是,如果我删除任何一行.channel(aggregatorOutputChannel())或.channel(confirmChannel()),这将不起作用,而且我必须在聚合器前后保留相同的频道.channel(aggregatorOutputChannel())。为什么我需要所有3频道
.channel(aggregatorOutputChannel())
或.channel(confirmChannel())
,这将不起作用,而且我必须在聚合器前后保留相同的频道.channel(aggregatorOutputChannel())
。为什么我需要所有3频道声明?如果这是错误的,如何纠正它
我使用的是JDK 8、Spring 5、Spring boot 2.0.4
@Configuration
@EnableIntegration
public class IntegrationConfig {
@Value("${agent.demographic.input.directory}")
private String inputDir;
@Value("${agent.demographic.output.directory}")
private String outputDir;
@Value("${confirmationfile.directory}")
private String confirmDir;
@Value("${input.scan.frequency: 2}")
private long scanFrequency;
@Value("${processing.waittime: 6000}")
private long messageGroupWaiting;
@Value("${thread.corepoolsize: 10}")
private int corepoolsize;
@Value("${thread.maxpoolsize: 20}")
private int maxpoolsize;
@Value("${thread.queuecapacity: 1000}")
private int queuedepth;
@Bean
public MessageSource<File> inputFileSource() {
FileReadingMessageSource src = new FileReadingMessageSource();
src.setDirectory(new File(inputDir));
src.setAutoCreateDirectory(true);
ChainFileListFilter<File> chainFileListFilter = new ChainFileListFilter<>();
chainFileListFilter.addFilter(new AcceptOnceFileListFilter<>() );
chainFileListFilter.addFilter(new RegexPatternFileListFilter("(?i)^.+\\.xml$"));
src.setFilter(chainFileListFilter);
return src;
}
@Bean
public UnZipTransformer unZipTransformer() {
UnZipTransformer unZipTransformer = new UnZipTransformer();
unZipTransformer.setExpectSingleResult(false);
unZipTransformer.setZipResultType(ZipResultType.FILE);
unZipTransformer.setDeleteFiles(true);
return unZipTransformer;
}
@Bean("agentdemographicsplitter")
public UnZipResultSplitter splitter() {
UnZipResultSplitter splitter = new UnZipResultSplitter();
return splitter;
}
@Bean
public DirectChannel outputChannel() {
return new DirectChannel();
}
@Bean
public DirectChannel aggregatorOutputChannel() {
return new DirectChannel();
}
@Bean("confirmChannel")
public DirectChannel confirmChannel() {
return new DirectChannel();
}
@Bean
public MessageHandler fileOutboundChannelAdapter() {
FileWritingMessageHandler adapter = new FileWritingMessageHandler(new File(outputDir));
adapter.setDeleteSourceFiles(true);
adapter.setAutoCreateDirectory(true);
adapter.setExpectReply(true);
adapter.setLoggingEnabled(true);
return adapter;
}
@Bean
public MessageHandler confirmationfileOutboundChannelAdapter() {
FileWritingMessageHandler adapter = new FileWritingMessageHandler(new File(confirmDir));
adapter.setDeleteSourceFiles(true);
adapter.setAutoCreateDirectory(true);
adapter.setExpectReply(false);
adapter.setFileNameGenerator(defaultFileNameGenerator() );
return adapter;
}
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corepoolsize);
executor.setMaxPoolSize(maxpoolsize);
executor.setQueueCapacity(queuedepth);
return executor;
}
@Bean
public DefaultFileNameGenerator defaultFileNameGenerator() {
DefaultFileNameGenerator defaultFileNameGenerator = new DefaultFileNameGenerator();
defaultFileNameGenerator.setExpression("payload.name");
return defaultFileNameGenerator;
}
@Bean
public IntegrationFlow confirmGeneration() {
return IntegrationFlows.
from("confirmChannel")
.handle(confirmationfileOutboundChannelAdapter())
.get();
}
@Bean
public IntegrationFlow individualProcessor() {
return flow -> flow.handle("thirdpartyIndividualAgentProcessor","processfile").channel(outputChannel()).handle(fileOutboundChannelAdapter());
}
@Bean
public IntegrationFlow firmProcessor() {
return flow -> flow.handle("thirdpartyFirmAgentProcessor","processfile").channel(outputChannel()).handle(fileOutboundChannelAdapter());
}
@Bean
public IntegrationFlow thirdpartyAgentDemographicFlow() {
return IntegrationFlows
.from(inputFileSource(), spec -> spec.poller(Pollers.fixedDelay(scanFrequency,TimeUnit.SECONDS)))
.channel(MessageChannels.executor(taskExecutor()))
.<File, Boolean>route(f -> f.getName().contains("individual"), m -> m
.subFlowMapping(true, sf -> sf.gateway(individualProcessor()))
.subFlowMapping(false, sf -> sf.gateway(firmProcessor()))
)
.channel(aggregatorOutputChannel())
.aggregate(aggregator -> aggregator.groupTimeout(messageGroupWaiting).correlationStrategy(new CorrelationStrategy() {
@Override
public Object getCorrelationKey(Message<?> message) {
return "xyz";
}
}))
.channel(aggregatorOutputChannel())
.handle("agentDemograpicOutput","generateAgentDemographicFile")
.channel(confirmChannel())
.get();
}
}
首先,
regexpaternFileListFilter
应该是ChainFileListFilter
中的第一个。这样,您就不会在AcceptOnceFileListFilter
中为您不感兴趣的文件增加内存开销
在第三方人口统计流的末尾需要.channel(confirmChannel())
,因为这是confirmGeneration
流的输入
我不认为你.channel(aggregatorOutputChannel())
必须隐式。
子流中也不需要.channel(outputChannel())
这不起作用
请详细说明:您得到了什么错误,然后它是如何工作的等等。。。
您还可以为org.springframework.integration
共享一些调试日志,以确定消息的传播方式
如果您在GitHub上共享一些简单的Spring Boot项目,让我们根据您提供的说明进行游戏和复制,也会有很大帮助
更新
我还注意到,您的聚合器基于groupTimeout()
。要将聚合消息发送到下游,您还需要在此配置:
/**
* @param sendPartialResultOnExpiry the sendPartialResultOnExpiry.
* @return the handler spec.
* @see AbstractCorrelatingMessageHandler#setSendPartialResultOnExpiry(boolean)
*/
public S sendPartialResultOnExpiry(boolean sendPartialResultOnExpiry) {
默认情况下,它是false
,因此您的消息确实会发送到NullChannel
。
查看文档中的更多信息:如果我没有.channel(outputChannel())文件OutboundChannelAdapter()如何将文件归档。如果我同时注释.channel(aggregatorOutputChannel())句柄。句柄(“AgentDemographicOutput”,“generateAgentDemographicFile”)将不会被调用。我没有收到任何错误,但它没有做任何事情。我不知道您的流程中有什么archive
,但如果它们只是DirectChannel
s,则您肯定不需要中间的通道:archive将文件从处理位置复制到另一个位置。fileOutboundChannelAdapter()从channelWell获取文件对象,您需要在代码中更加明确,我只是在代码中没有看到任何存档
字。。。
/**
* @param sendPartialResultOnExpiry the sendPartialResultOnExpiry.
* @return the handler spec.
* @see AbstractCorrelatingMessageHandler#setSendPartialResultOnExpiry(boolean)
*/
public S sendPartialResultOnExpiry(boolean sendPartialResultOnExpiry) {