【问题标题】:SftpRemoteFileTemplate does not work with RemoteDirectoryExpression when @Autowired当@Autowired 时,SftpRemoteFileTemplate 不适用于 RemoteDirectoryExpression
【发布时间】:2020-11-27 09:32:28
【问题描述】:

下面是我正在使用的配置

@Autowired
private SftpRemoteFileTemplate outboundTemplate;

@Autowired
private SftpConfig config;


@Bean
@ServiceActivator(inputChannel = "sftpOutputGenericChannel")
public MessageHandler simplehandler() {
    SftpMessageHandler handler = new SftpMessageHandler(outboundTemplate, FileExistsMode.APPEND);
    handler.setRemoteDirectoryExpression(new LiteralExpression(config.getDirectory()));
    handler.setFileNameGenerator((Message<?> message) -> ((String) message.getHeaders().get(KEY)));
    handler.setUseTemporaryFileName(false);
    return handler;
}

我在单独的 Config 类中创建了 Sessionfactory、CachingSessionfactory 和 SftpRemoteFileTemplte,它们正在正确实例化,下面是相同的日志。

2020-11-27 01:15:17.742 [main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'cachingSessionFactory'
2020-11-27 01:15:17.744 [main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'sftpSessionFactory'
2020-11-27 01:15:17.778 [main] o.s.b.f.s.DefaultListableBeanFactory     : Autowiring by type from bean name 'cachingSessionFactory' via factory method to bean named 'sftpSessionFactory'
2020-11-27 01:15:17.783 [main] o.s.integration.util.SimplePool          : Target pool size changed by -2147483637, now 10
2020-11-27 01:15:54.434 [main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'outboundTemplate'
2020-11-27 01:15:54.435 [main] o.s.b.f.s.DefaultListableBeanFactory     : Autowiring by type from bean name 'outboundTemplate' via factory method to bean named 'cachingSessionFactory'

当我执行此代码时,Spring DEBUG 日志显示文件已成功发送到服务器,但实际上文件没有上传到服务器。

但如果我将MessageHandler 的实现更改为,

SftpMessageHandler handler = new SftpMessageHandler(new SftpRemoteFileTemplate(cachingSessionFactory), FileExistsMode.APPEND);

它开始工作,文件实际上被上传到服务器,不知道为什么会这样?

当我将@Autowired SftpRemoteFileTemplatehandler.setRemoteDirectoryExpressionString("headers['remote_directory']") 一起使用时,再观察一次,效果非常好。

我想了解 SftpRemoteTemplate 在此处的工作方式以及建议的最佳做法是什么?

注意:SpringBoot v2.4.0 Spring 集成:5.4.1,在引导 v2.2.6.RELEASE 时遇到了类似的问题

【问题讨论】:

    标签: java spring spring-boot spring-integration spring-integration-sftp


    【解决方案1】:

    您可能在其他地方使用相同的SftpRemoteFileTemplate,并且您还在那里修改它以获得其他选项。事实上,像handler.setRemoteDirectoryExpression() 这样的东西对提供的SftpRemoteFileTemplate 做了一个委托,因此发生了突变:

    /**
     * Specify a remote directory path SpEL expression.
     * @param remoteDirectoryExpression the remote directory expression
     * @see RemoteFileTemplate#setRemoteDirectoryExpression(Expression)
     */
    public void setRemoteDirectoryExpression(Expression remoteDirectoryExpression) {
        this.remoteFileTemplate.setRemoteDirectoryExpression(remoteDirectoryExpression);
    }
    

    因此,当另一个地方进行类似的修改时,您最终会遇到竞争条件,并且您的文件可能会转移到另一个地方。

    最佳做法是将RemoteFileTemplate 视为prototype,并为每个通道适配器创建一个实例。或者只是使用另一个 ctor - 仅基于 SessionFactory

    /**
     * @param sessionFactory the session factory.
     * @see FileTransferringMessageHandler#FileTransferringMessageHandler
     * (SessionFactory)
     */
    public SftpMessageHandler(SessionFactory<LsEntry> sessionFactory)
    

    我们可能需要修改FileTransferringMessageHandler 中的逻辑以拒绝外部提供的RemoteFileTemplate 的突变。随意提出一个 GH 问题,我们将在下一个主要版本中看到我们可以做些什么,我们可以在其中做一些重大更改。

    【讨论】:

    • 感谢 Artem,我现在将只使用新的 SftpRemoteFileTemplate。我尝试过使用 PROTOTYPE 范围和多个其他选项,例如在初始化 SftpRemoteFileTemplate 时设置远程目录而不调用处理程序的方法等,但结果是相同的。我可以使用另一个只使用 SessionFactory 但不确定它会给我一个选项以追加模式写入文件?这样我就不需要到处使用 SftpRemoteFileTemplate
    猜你喜欢
    • 2014-10-29
    • 2014-07-16
    • 2013-11-07
    • 2017-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 2013-05-13
    相关资源
    最近更新 更多