Можно ли динамически изменить имя-регулярного выражения в 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.
См. Справочное руководство для получения дополнительной информации. Образец, который вы упоминаете в своих вопросах, также содержит фрагмент кода шлюза.