如何使用Spring Integration with Java config通过SFTP每天获取一个文件?

时间:2016-08-29 20:25:33

标签: spring-integration spring-java-config spring-retry

我需要每天通过SFTP获取一个文件。我想使用Spring Integration with Java config。该文件通常在每天的特定时间提供。应用程序应该尝试每天在该时间附近获取文件。如果该文件不可用,则应继续重试x次尝试。在x尝试之后,它应该发送一封电子邮件,让管理员知道该文件在SFTP站点上仍然不可用。

一种选择是使用SftpInboundFileSynchronizingMessageSource。在MessageHandler中,我可以开始处理文件。但是,我真的不需要与远程文件系统同步。毕竟,它是文件的预定交付。另外,我需要延迟最多15分钟才能进行下一次重试,并且每15分钟轮询一次对于每日文件来说似乎有点过分。我想我可以使用它,但需要一些机制来在经过一段时间后发送电子邮件并且没有收到任何文件。

另一个选项似乎是使用SFTP出站网关的get。但我能找到的唯一例子似乎是XML配置。

更新

使用Artem Bilan提供的帮助后添加代码:

配置类:

@Bean
@InboundChannelAdapter(autoStartup="true", channel = "sftpChannel", poller = @Poller("pollerMetadata"))
public SftpInboundFileSynchronizingMessageSource sftpMessageSource(ApplicationProperties applicationProperties, PropertiesPersistingMetadataStore store) {
    SftpInboundFileSynchronizingMessageSource source =
            new SftpInboundFileSynchronizingMessageSource(sftpInboundFileSynchronizer(applicationProperties));
    source.setLocalDirectory(new File("ftp-inbound"));
    source.setAutoCreateLocalDirectory(true);
    FileSystemPersistentAcceptOnceFileListFilter local = new FileSystemPersistentAcceptOnceFileListFilter(store,"test");
    source.setLocalFilter(local);
    source.setCountsEnabled(true);        
    return source;
}

@Bean
public PollerMetadata pollerMetadata() {
    PollerMetadata pollerMetadata = new PollerMetadata();
    List<Advice> adviceChain = new ArrayList<Advice>();
    adviceChain.add(retryCompoundTriggerAdvice());
    pollerMetadata.setAdviceChain(adviceChain);
    pollerMetadata.setTrigger(compoundTrigger());
    return pollerMetadata;
}

@Bean
public RetryCompoundTriggerAdvice retryCompoundTriggerAdvice() {
    return new RetryCompoundTriggerAdvice(compoundTrigger(), secondaryTrigger());
}

@Bean
public CompoundTrigger compoundTrigger() {
    CompoundTrigger compoundTrigger = new CompoundTrigger(primaryTrigger());
    return compoundTrigger;
}

@Bean
public Trigger primaryTrigger() {
    return new CronTrigger("*/60 * * * * *");
}

@Bean
public Trigger secondaryTrigger() {
    return new PeriodicTrigger(10000);
}

@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler handler(PropertiesPersistingMetadataStore store) {
    return new MessageHandler() {

        @Override
        public void handleMessage(Message<?> message) throws MessagingException {
            System.out.println(message.getPayload());
            store.flush();
        }

    };
}

RetryCompoundTriggerAdvice类:

public class RetryCompoundTriggerAdvice extends AbstractMessageSourceAdvice {

    private final CompoundTrigger compoundTrigger;

    private final Trigger override;

    private int count = 0;

    public RetryCompoundTriggerAdvice(CompoundTrigger compoundTrigger, Trigger overrideTrigger) {
        Assert.notNull(compoundTrigger, "'compoundTrigger' cannot be null");
        this.compoundTrigger = compoundTrigger;
        this.override = overrideTrigger;
    }

    @Override
    public boolean beforeReceive(MessageSource<?> source) {
        return true;
    }

    @Override
    public Message<?> afterReceive(Message<?> result, MessageSource<?> source) {
        if (result == null && count <= 5) {
            count++;
            this.compoundTrigger.setOverride(this.override);
        }
        else {
            this.compoundTrigger.setOverride(null);
            if (count > 5) {
                 //send email
            }
            count = 0;
        }
        return result;
    }
}

1 个答案:

答案 0 :(得分:2)

自Spring Integration 4.3起,CompoundTrigger

* A {@link Trigger} that delegates the {@link #nextExecutionTime(TriggerContext)}
* to one of two Triggers. If the {@link #setOverride(Trigger) override} trigger is
* {@code null}, the primary trigger is invoked; otherwise the override trigger is
* invoked.

CompoundTriggerAdvice

的组合
* An {@link AbstractMessageSourceAdvice} that uses a {@link CompoundTrigger} to adjust
* the poller - when a message is present, the compound trigger's primary trigger is
* used to determine the next poll. When no message is present, the override trigger is
* used.

它可用于完成任务:

primaryTrigger可以是CronTrigger,每天只运行一次任务。

override可能是PeriodicTrigger,需要短暂的重试时间。

retry逻辑,您可以使用另外一个Advice进行投询,或者只是扩展CompoundTriggerAdvice以添加count逻辑以最终发送电子邮件。

由于没有文件,因此没有消息来启动流程。除非在poller基础设施周围跳舞,否则我们没有选择。