当@Autowired 时,SftpRemoteFileTemplate 不适用于 RemoteDirectoryExpression
SftpRemoteFileTemplate does not work with RemoteDirectoryExpression when @Autowired
以下是我使用的配置
@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;
}
我在单独的配置中创建了 Sessionfactory、CachingSessionfactory 和 SftpRemoteFileTemplte class,并且它们正在正确实例化,下面是相同的日志。
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调试日志显示文件已成功发送到服务器,但实际上文件没有上传到服务器。
但如果我将 MessageHandler
的实现更改为
SftpMessageHandler handler = new SftpMessageHandler(new SftpRemoteFileTemplate(cachingSessionFactory), FileExistsMode.APPEND);
它开始工作并且文件实际上传到服务器,不确定为什么会这样?
当我将 @Autowired SftpRemoteFileTemplate
与 handler.setRemoteDirectoryExpressionString("headers['remote_directory']")
一起使用时,再观察一次,效果非常好。
我想了解 SftpRemoteTemplate 在这里是如何工作的,建议的最佳做法是什么?
注意:SpringBoot v2.4.0 Spring 集成:5.4.1,面临与 boot v2.2 类似的问题。6.RELEASE
您可能在其他地方使用了相同的 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 问题,我们将在下一个主要版本中看到我们可以做什么,在那里我们可以做一些重大更改。
以下是我使用的配置
@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;
}
我在单独的配置中创建了 Sessionfactory、CachingSessionfactory 和 SftpRemoteFileTemplte class,并且它们正在正确实例化,下面是相同的日志。
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调试日志显示文件已成功发送到服务器,但实际上文件没有上传到服务器。
但如果我将 MessageHandler
的实现更改为
SftpMessageHandler handler = new SftpMessageHandler(new SftpRemoteFileTemplate(cachingSessionFactory), FileExistsMode.APPEND);
它开始工作并且文件实际上传到服务器,不确定为什么会这样?
当我将 @Autowired SftpRemoteFileTemplate
与 handler.setRemoteDirectoryExpressionString("headers['remote_directory']")
一起使用时,再观察一次,效果非常好。
我想了解 SftpRemoteTemplate 在这里是如何工作的,建议的最佳做法是什么?
注意:SpringBoot v2.4.0 Spring 集成:5.4.1,面临与 boot v2.2 类似的问题。6.RELEASE
您可能在其他地方使用了相同的 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 问题,我们将在下一个主要版本中看到我们可以做什么,在那里我们可以做一些重大更改。