java - 是否可以动态更改入站 channel 适配器的文件名正则表达式

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

在我们的应用程序中,有大量文件从远程计算机下载到本地计算机(运行代码的服务器)。我们选择使用 Spring SFTP 进行下载。我们仍处于发展过程中。

当用户选择一个文件并单击 UI 中的按钮下载该文件时,就会启动下载过程。多个用户可能同时选择不同的文件并将它们从远程计算机下载到本地计算机(运行代码的服务器)。对于所有下载请求,远程计算机(以及下载发生的路径)和本地计算机(以及下载文件的路径)都是相同的,只是文件名不同。

在下面的代码中,我在 int-sftp:inbound-channel-adapter 中设置 filename-regex。问题是文件名正则表达式是静态的。我需要动态设置文件名正则表达式。因为每个用户都会下载不同的文件。我无法在文件名正则表达式中使用正则表达式,因为只需要下载选定的文件。

是否可以动态设置。我必须对我的代码进行哪些更改才能做到这一点。欢迎所有建议。提前致谢。

<bean id="sftpSessionFactory" class="org.springframework.integration.file.remote.session.CachingSessionFactory">
    <constructor-arg ref="defaultSftpSessionFactory" />
</bean>

<bean id="defaultSftpSessionFactory"
      class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
    <property name="host" value="${sftp.host}"/>
    <property name="privateKey" value="${sftp.private.keyfile}"/>
    <property name="privateKeyPassphrase" value="${sftp.passphrase}"/>
    <property name="port" value="${sftp.port}"/>
    <property name="user" value="${sftp.username}"/>
    <property name="allowUnknownKeys" value="true"/>
</bean>

<bean class="com.rizwan.test.sftp_inbound_channel_adapter.EmbeddedSftpServer">
    <property name="port" value="${sftp.port}"/>
    <property name="defaultSftpSessionFactory" ref="defaultSftpSessionFactory"/>
</bean>

<int-sftp:inbound-channel-adapter id="sftpInbondAdapter"
        auto-startup="false"
        channel="receiveChannel"
        session-factory="sftpSessionFactory"
        local-directory="file:local-dir"
        remote-directory="si.sftp.sample"
        auto-create-local-directory="true"
        delete-remote-files="false"
        filename-regex="a.txt">
    <int:poller fixed-rate="0" max-messages-per-poll="-1"/>
</int-sftp:inbound-channel-adapter>

<int:channel id="receiveChannel">
    <int:queue/>
</int:channel>

下面是我在 main 方法中的 java 代码。

PollableChannel localFileChannel = context.getBean("receiveChannel", PollableChannel.class);
SourcePollingChannelAdapter adapter = context.getBean(SourcePollingChannelAdapter.class);
adapter.start();
adapter.stop();
Message<?> received = localFileChannel.receive();

已使用此链接供我引用 - https://github.com/spring-projects/spring-integration-samples/tree/master/basic/sftp


根据 Artem Bilan 给出的答案发布配置以使其工作。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration/sftp http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd">

<import resource="SftpSampleCommon.xml"/>

<int:gateway id="gw" service-interface="com.rizwan.test.sftp_outbound_gateway.ToSftpFlowGateway"
    default-request-channel="toGet"/>

<int-sftp:outbound-gateway id="gatewayGET"
    local-directory="C:\Users\503017993\Perforce\rizwan.shaikh1_G7LGTPC2E_7419\NGI\DEV\Jetstream_Branches\C360_Falcon2_1_Main\sftp-outbound-gateway"
    session-factory="sftpSessionFactory"
    request-channel="toGet"
    remote-directory="/si.sftp.sample"
    command="get"
    command-options="-P"
    expression="payload">
    <int-sftp:request-handler-advice-chain>
        <int:retry-advice />
    </int-sftp:request-handler-advice-chain>
</int-sftp:outbound-gateway>
</beans>

Java代码:

ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
            "classpath:/META-INF/spring-context.xml");
DownloadRemoteFileGateway downloadGateway = ctx.getBean(DownloadRemoteFileGateway.class);
String downloadedFilePath = downloadGateway.downloadRemoteFile("si.sftp.sample/2ftptest");

最佳答案

你所追求的方法是绝对错误的。您没有考虑不同用户对组件的并发访问。现在让我们想象一下我们能够更改 filename-regex从最终用户的角度来看。其中一个想要下载他/她自己的文件,因此他/她设置了适当的模式并调用 adapter.start() 。同时另一个用户想要下载他/她的文件。瞧 - 我们有一个竞争条件,因为当组件在用户范围内不起作用时,您会同时更改组件的状态。 SourcePollingChannelAdapter的性质活跃。一旦启动它,后台计划任务将旋转该组件直到停止。

解决方案中的另一个瓶颈是访问 PollableChannel 。让我们想象一下我们可以制作 SourcePollingChannelAdapter在用户上下文中工作,并且我们没有任何并发​​突变和竞争条件。但是,当该组件下载文件时,它会将消息发送给 PollableChannel 。是否可以保证一个用户不会从该队列中为另一用户提取文件?..

您的解决方案所需要的应该是被动且无状态的。这确实必须由最终用户发起并在同一线程中返回一些答案。为此,您应该查看 <int-sftp:outbound-gateway>及其 getmget命令。正是这个能够从 Message 获取文件名/模式您发送后,从 SFTP 下载并将其返回给调用者。您可以放置​​@MessagingGateway在该 SFTP 网关前面,并且只有来自 MVC Controller 的纯 Java 代码。

参见Reference Manual了解更多信息。您在问题中提到的示例也带来了一些网关片段。

关于java - 是否可以动态更改入站 channel 适配器的文件名正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48522866/

相关文章:

java - 我们如何将 REST 服务部署为 jar?

java - PowerMock,模拟一个静态方法,然后在所有其他静态上调用真实方法

spring - 如何在运行时将新用户添加到 Spring Security

使用注释的 Spring Integration 和 Spring Batch [Spring-Batch-Integration]

java - Spring Cloud Stream Kafka 记录太大

Spring MessageBuilder 与 Spring Integration MessageBuilder

java - 将字符串转换为消息对象 Android 应用程序

Java 8 : IntStream to Integer[]

java - 在类路径资源 + Springboot 中创建名称为 'dataSource' 的 bean 时出错

java - 如何在 Spring XD 中向 "side channel"发送消息?