Можно ли динамически изменить имя-регулярного выражения в inbound-channel-adapter

В нашем приложении огромное количество файлов, загруженных с удаленного компьютера на локальный компьютер (сервер, на котором выполняется код). Мы решили использовать Spring SFTP для загрузки. Мы все еще в процессе разработки.

Процесс загрузки начинается, когда пользователь выбирает файл, щелкает кнопку в пользовательском интерфейсе, чтобы загрузить этот файл. Одновременно несколько пользователей могут выбирать разные файлы и загружать их с удаленного компьютера на локальный компьютер (сервер, на котором выполняется код). Удаленный компьютер (и путь, откуда будет происходить загрузка) и локальный компьютер (и путь, по которому будет загружен файл) одинаковы для всех запросов на загрузку, только имя файла будет другим.

В моем коде ниже я устанавливаю имя-регулярного выражения в int-sftp:inbound-channel-adapter. Проблема в том, что filename-regex является статическим. Мне нужно установить имя-файла динамически. Потому что каждый пользователь будет загружать разные файлы. Я не могу использовать 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>

Ниже мой код Java внутри метода main.

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


Размещение конфигурации для выполнения этой работы основано на ответе Артема Билана.

<?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 ответ

Решение

Подход, который вы придерживаетесь, абсолютно неверен. Вы не учитываете одновременный доступ к компоненту от разных пользователей. Теперь давайте представим, что мы сможем изменить filename-regex с точки зрения конечного пользователя. Один из них хочет загрузить свой собственный файл, поэтому он устанавливает соответствующий шаблон и вызывает adapter.start(), В то же время другой пользователь хотел бы загрузить свой файл. И вуаля - у нас есть условие гонки, потому что вы изменяете состояние компонента одновременно, когда он не работает в пользовательской области. Природа SourcePollingChannelAdapter быть активным. После запуска фоновая запланированная задача будет вращать этот компонент до остановки.

Еще одним узким местом в вашем решении является доступ к PollableChannel, Давайте представим, что мы можем сделать SourcePollingChannelAdapter работать в контексте пользователя, и у нас нет никаких одновременных мутаций и условий гонки. Но когда этот компонент загружает файлы, он помещает сообщения PollableChannel, Есть ли гарантия, что один пользователь не извлечет из этой очереди файлы для другого пользователя?..

То, что вам нужно для вашего решения, должно быть пассивным и не имеющим состояния. И это действительно должно инициироваться конечным пользователем и возвращать некоторый ответ в том же потоке. Для этого вы должны взглянуть на <int-sftp:outbound-gateway> И его get или же mget команды. Именно этот может получить имя файла / шаблон из Message Вы отправляете, загружаете его из SFTP и возвращаете его вызывающей стороне. Вы можете разместить @MessagingGateway перед этим шлюзом SFTP и просто простой Java-код из контроллера MVC.

См. Справочное руководство для получения дополнительной информации. Образец, который вы упоминаете в своих вопросах, также содержит фрагмент кода шлюза.

Другие вопросы по тегам