是否可以动态更改入站通道适配器的filename-regex

时间:2018-01-30 13:39:16

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

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

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

在下面的代码中,我在int-sftp:inbound-channel-adapter中设置了filename-regex。问题是filename-regex是静态的。我需要动态设置filename-regex。因为每个用户都将下载不同的文件。我不能在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");

1 个答案:

答案 0 :(得分:2)

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

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

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

有关详细信息,请参阅Reference Manual。您在问题中提到的示例也带来了一些网关片段。