Spring integration Spring集成邮件:在所有数据库插入后发送电子邮件

Spring integration Spring集成邮件:在所有数据库插入后发送电子邮件,spring-integration,spring-integration-dsl,spring-integration-ftp,spring-integration-jdbc,Spring Integration,Spring Integration Dsl,Spring Integration Ftp,Spring Integration Jdbc,您好,我有一个集成流,它逐行分割一个文件,将每一行转换为一个POJO,然后通过JDBC出站网关将该POJO插入数据库 我想能够发送一个单一的电子邮件一旦文件的过程已经完成。 我目前在jdbcOutboundGateway之后发送到smtpFlow频道,但这是在每次插入db之后发送一封电子邮件 这是我当前的DSL流 IntegrationFlow ftpFlow() { return IntegrationFlows.from( ftpSource(), spec

您好,我有一个集成流,它逐行分割一个文件,将每一行转换为一个POJO,然后通过JDBC出站网关将该POJO插入数据库

我想能够发送一个单一的电子邮件一旦文件的过程已经完成。 我目前在jdbcOutboundGateway之后发送到smtpFlow频道,但这是在每次插入db之后发送一封电子邮件

这是我当前的DSL流

IntegrationFlow ftpFlow() {
    return IntegrationFlows.from(
            ftpSource(), spec -> spec.poller(Pollers.fixedDelay(5, TimeUnit.SECONDS)))
            .split(splitFile())
            .transform(this::transformToIndividualScore)
            .handle(jdbcOutboundGateway(null))
            .channel("smtpFlow")
            .get();
如何使此流在
jdbcOutboundGateway
中处理完所有文件后只发送一封电子邮件

这是我的
splitFile()
方法

@Bean
FileSplitter splitFile() {
    FileSplitter fs = new FileSplitter(true, false);
    fs.setFirstLineAsHeader("IndividualScore");
    return fs;
@Transformer
private IndividualScore transformToIndividualScore(String payload) {
    String[] values = payload.split(",");
    IndividualScore is = new IndividualScore();
    is.setScorecardDate(values[0]);
    is.setVnSpId(values[1]);
    is.setPrimaryCat(values[2]);
    is.setSecondaryCat(values[3]);
    is.setScore(Integer.parseInt(values[4]));
    is.setActual(values[5]);
    return is;
}
下面是我的
转换为IndividualScore
方法

@Bean
FileSplitter splitFile() {
    FileSplitter fs = new FileSplitter(true, false);
    fs.setFirstLineAsHeader("IndividualScore");
    return fs;
@Transformer
private IndividualScore transformToIndividualScore(String payload) {
    String[] values = payload.split(",");
    IndividualScore is = new IndividualScore();
    is.setScorecardDate(values[0]);
    is.setVnSpId(values[1]);
    is.setPrimaryCat(values[2]);
    is.setSecondaryCat(values[3]);
    is.setScore(Integer.parseInt(values[4]));
    is.setActual(values[5]);
    return is;
}

在句柄之后添加
.aggregate()
,将拆分结果重新组合成一条消息。

这是我的问题的解决方案(某种程度上)

在我的
filespliter
上将迭代器标记为
false
,现在允许排序头

更新的
splitFile()
如下所示

@Bean
FileSplitter splitFile() {
    FileSplitter fs = new FileSplitter(false, false);
    fs.setFirstLineAsHeader("IndividualScore");
    fs.setApplySequence(true);
    return fs;
}
我的直觉告诉我,默认的
.aggregate()
发布策略必须是消息头
sequenceSize
==聚合的消息列表

创建
filespliter
时,将
iterator
设置为
true
时,
sequenceSize
设置为
0
,这将永远不会满足默认
.aggregate()的发布策略

但是,这使得
filespliter
使用
列表
将文件的所有行存储在内存中。聚合器还在内存中存储另一个
ArrayList


有没有更好的解决方案来创建一个自定义聚合器来处理
END
FileMarker
以允许使用迭代器来拆分文件?

借助@ArtemBilan

我能够使用
publishsubscribebchannel()
和chain 2
subscribe()
方法,下面是新的
IntegrationFlow

 @Bean
IntegrationFlow ftpFlow() {
    return IntegrationFlows.from(
            ftpSource(), spec -> spec.poller(Pollers.fixedDelay(5, TimeUnit.SECONDS)))
            .publishSubscribeChannel(channel -> channel
                    .subscribe(
                        a -> a
                                .split(splitFile())
                                .transform(this::transformToIndividualScore)
                                .handle(jdbcMessageHandler(null)))
                    .subscribe(
                        b -> b
                                .transform(this::transformToSuccessEmail)
                                .handle(emailHandler()))
            )
            .get();

另一种方法是使用带有
split()
jdbcOutboundGateway()
publishSubscribeChannel()
作为一个订阅者子流,使用
Mail.outboundAdapter()
作为另一个订阅者子流。确实不可能一次完成所有文件的请求:只是没有一个标志来检查所有文件是否完成。如果在处理现有文件的过程中出现新文件,该怎么办?。。考虑将逻辑更改为基于每个文件的基础。或者正如Gary所说:使用一些聚合器策略,在一些文件或超时后发出电子邮件消息;抱歉,我误解了这个问题-聚合器将为每个文件发送一封邮件,而不是为每个插入发送一封邮件;您需要@ArtemBilan对所有文件的一条消息的建议。当我在
.handle(jdbcOutboundGateway(null))
之后删除
.aggregate()
时,它没有完成流程,只是挂起。@ArtemBilan是的!这对我来说现在有意义了。我对集成非常陌生,它是一个很好的框架。我将很快更新我的代码并发布一条新的消息和解决方案。