java - 当@Autowired 时,SftpRemoteFileTemplate 不适用于 RemoteDirectoryExpression

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

下面是我使用的配置

@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 类似的问题

最佳答案

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

/**
 * 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 并且每个 channel 适配器都有一个实例。或者只是使用另一个 ctor - 仅基于 SessionFactory:

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

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

关于java - 当@Autowired 时,SftpRemoteFileTemplate 不适用于 RemoteDirectoryExpression,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65034937/

相关文章:

java - 为什么我的 @Scheduled Spring Boot 任务在 Azure 中运行不一致?

spring-boot - react 环境中的 spring-cloud-sleuth

java - Spring测试集成未运行我如何处理这个错误?

java - Flux 是如何垃圾收集的?

java - 如果 ActiveMQ 未启动,Spring 容器将挂起

java - 获取 JPAQuery 结果作为页面

java - Spring JdbcTemplate - 如何为实现 Multi-Tenancy 添加每个查询?

javascript - Spring 表单标签复选框(表单 :checkbox) hidden field not sent to server?

java - 如何使用 Spring Security 4.0.1.RELEASE 使用 Auth Token 实现 Rest Full Web 服务

java - Spring Boot + Cloud Firestore 集成测试