SMB サポート
Spring Integration は、SMB を使用したファイル転送操作をサポートします。
サーバーメッセージブロック [Wikipedia] (英語) (SMB) は、共有ファイルサーバーにファイルを転送できるシンプルなネットワークプロトコルです。
この依存関係をプロジェクトに含める必要があります。
概要
CIFS/SMB ネットワークプロトコルの Java 実装として、Java CIFS [GitHub] (英語) クライアントライブラリが選択されました。その SmbFile
抽象化は、SmbSession
、SmbRemoteFileTemplate
などの Spring Integration 「リモートファイル」基盤に単純にラップされます。
SMB チャネルアダプターとサポートクラスの実装は、(S)FTP または AWS S3 プロトコルの既存のコンポーネントと完全に似ています。これらのコンポーネントに精通していれば、使用するのは非常に簡単です。
Spring Integration は、受信チャネルアダプター、送信チャネルアダプター、および送信ゲートウェイの 3 つのクライアント側エンドポイントを提供することにより、SMB を介したファイルの送受信をサポートします。また、これらのクライアントコンポーネントを定義するための便利な名前空間ベースの構成オプションも提供します。
SMB 名前空間を使用するには、XML ファイルのヘッダーに次を追加します。
xmlns:int-smb="http://www.springframework.org/schema/integration/smb"
xsi:schemaLocation="http://www.springframework.org/schema/integration/smb
https://www.springframework.org/schema/integration/smb/spring-integration-smb.xsd"
SMB セッションファクトリ
SMB アダプターを構成する前に、SMB セッションファクトリを構成する必要があります。次の例に示すように、通常の Bean 定義を使用して SMB セッションファクトリを構成できます。
SmbSessionFactory
は、最小 / 最大バージョンで SMB プロトコルを設定するオプションを公開します。例: SMB 2.1 の最小バージョンと SMB 3.1.1 の最大バージョンをサポートします。
@Bean
public SmbSessionFactory smbSessionFactory() {
SmbSessionFactory smbSession = new SmbSessionFactory();
smbSession.setHost("myHost");
smbSession.setPort(445);
smbSession.setDomain("myDomain");
smbSession.setUsername("myUser");
smbSession.setPassword("myPassword");
smbSession.setShareAndDir("myShareAndDir");
smbSession.setSmbMinVersion(DialectVersion.SMB210);
smbSession.setSmbMaxVersion(DialectVersion.SMB311);
return smbSession;
}
SmbSessionFactory
はカスタム jcifs.CIFSContext
で初期化できます。
SMB プロトコルの最小 / 最大バージョンの設定は、jcifs.CIFSContext の実装で行う必要があります。 |
@Bean
public SmbSessionFactory smbSessionFactory() {
SmbSessionFactory smbSession = new SmbSessionFactory(new MyCIFSContext());
smbSession.setHost("myHost");
smbSession.setPort(445);
smbSession.setDomain("myDomain");
smbSession.setUsername("myUser");
smbSession.setPassword("myPassword");
smbSession.setShareAndDir("myShareAndDir");
return smbSession;
}
SMB 受信チャネルアダプター
SMB ファイルをローカルにダウンロードするために、SmbInboundFileSynchronizingMessageSource
が提供されています。SmbInboundFileSynchronizer
インジェクションを必要とする AbstractInboundFileSynchronizingMessageSource
の単純な拡張です。リモートファイルをフィルタリングするために、既存の FileListFilter
実装を引き続き使用できますが、特定の SmbRegexPatternFileListFilter
および SmbSimplePatternFileListFilter
が提供されています。
@Bean
public SmbInboundFileSynchronizer smbInboundFileSynchronizer() {
SmbInboundFileSynchronizer fileSynchronizer =
new SmbInboundFileSynchronizer(smbSessionFactory());
fileSynchronizer.setFilter(compositeFileListFilter());
fileSynchronizer.setRemoteDirectory("mySharedDirectoryPath");
fileSynchronizer.setDeleteRemoteFiles(true);
return fileSynchronizer;
}
@Bean
public CompositeFileListFilter<SmbFile> compositeFileListFilter() {
CompositeFileListFilter<SmbFile> filters = new CompositeFileListFilter<>();
filters.addFilter(new SmbRegexPatternFileListFilter("^(?i).+((\\.txt))$"));
return filters;
}
@Bean
public MessageChannel smbFileInputChannel() {
return new DirectChannel();
}
@Bean
@InboundChannelAdapter(value = "smbFileInputChannel",
poller = @Poller(fixedDelay = "2000"))
public MessageSource<File> smbMessageSource() {
SmbInboundFileSynchronizingMessageSource messageSource =
new SmbInboundFileSynchronizingMessageSource(smbInboundFileSynchronizer());
messageSource.setLocalDirectory(new File("myLocalDirectoryPath"));
messageSource.setAutoCreateLocalDirectory(true);
return messageSource;
}
XML 構成用に、<int-smb:inbound-channel-adapter>
コンポーネントが提供されています。
バージョン 6.2 以降では、SmbLastModifiedFileListFilter
を使用して、最終変更戦略に基づいて SMB ファイルをフィルタリングできます。このフィルターは age
プロパティを使用して構成でき、この値よりも古いファイルのみがフィルターを通過するようになります。デフォルトの経過時間は 60 秒ですが、(ネットワーク障害などによる) 早期にファイルが選択されることを避けるために、十分な長さを選択する必要があります。詳細については、Javadoc を参照してください。
Java DSL を使用した構成
次の Spring Boot アプリケーションは、Java DSL で受信アダプターを構成する方法の例を示しています。
@SpringBootApplication
public class SmbJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(SmbJavaApplication.class)
.web(false)
.run(args);
}
@Bean
public SmbSessionFactory smbSessionFactory() {
SmbSessionFactory smbSession = new SmbSessionFactory();
smbSession.setHost("myHost");
smbSession.setPort(445);
smbSession.setDomain("myDomain");
smbSession.setUsername("myUser");
smbSession.setPassword("myPassword");
smbSession.setShareAndDir("myShareAndDir");
smbSession.setSmbMinVersion(DialectVersion.SMB210);
smbSession.setSmbMaxVersion(DialectVersion.SMB311);
return smbSession;
}
@Bean
public IntegrationFlow smbInboundFlow() {
return IntegrationFlow
.from(Smb.inboundAdapter(smbSessionFactory())
.preserveTimestamp(true)
.remoteDirectory("smbSource")
.regexFilter(".*\\.txt$")
.localFilename(f -> f.toUpperCase() + ".a")
.localDirectory(new File("d:\\smb_files")),
e -> e.id("smbInboundAdapter")
.autoStartup(true)
.poller(Pollers.fixedDelay(5000)))
.handle(m -> System.out.println(m.getPayload()))
.get();
}
}
SMB ストリーミング受信チャネルアダプター
このアダプターは、型 InputStream
のペイロードを含むメッセージを生成し、ローカルファイルシステムに書き込むことなくファイルを取得できるようにします。セッションは開いたままであるため、ファイルが消費されると、消費側のアプリケーションがセッションを閉じる必要があります。セッションは closeableResource
ヘッダー (IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE
) で提供されます。FileSplitter
や StreamTransformer
などの標準フレームワークコンポーネントは、セッションを自動的に閉じます。これらのコンポーネントの詳細については、ファイル分割およびストリームトランスを参照してください。次の例は、inbound-streaming-channel-adapter
を構成する方法を示しています。
<int-smb:inbound-streaming-channel-adapter id="smbInbound"
channel="smbChannel"
session-factory="sessionFactory"
filename-pattern="*.txt"
filename-regex=".*\.txt"
filter="filter"
filter-expression="@myFilterBean.check(#root)"
remote-file-separator="/"
comparator="comparator"
max-fetch-size="1"
remote-directory-expression="'foo/bar'">
<int:poller fixed-rate="1000" />
</int-smb:inbound-streaming-channel-adapter>
filename-pattern
、filename-regex
、filter
または filter-expression
のいずれか 1 つのみが許可されます。
SmbStreamingMessageSource
アダプターは、メモリ内 SimpleMetadataStore
に基づく SmbPersistentAcceptOnceFileListFilter
を使用して リモートファイルの重複を防ぎます。デフォルトでは、このフィルターはファイル名パターン (または正規表現) にも適用されます。重複を許可する必要がある場合は、AcceptAllFileListFilter
を使用できます。その他のユースケースは CompositeFileListFilter
(または ChainFileListFilter
) で処理できます。Java 構成 ( ドキュメントの後半) は、重複を避けるために処理後に リモートファイルを削除する 1 つの手法を示しています。
SmbPersistentAcceptOnceFileListFilter
の詳細と使用方法については、リモート永続ファイルリストフィルターを参照してください。
max-fetch-size
属性を使用して、フェッチが必要なときに各ポーリングでフェッチされるファイルの数を制限します。1
に設定し、クラスター環境で実行する場合は永続フィルターを使用します。詳細については、受信チャネルアダプター: リモートファイルフェッチの制御を参照してください。
アダプターは、リモートディレクトリとファイル名をそれぞれ FileHeaders.REMOTE_DIRECTORY
ヘッダーと FileHeaders.REMOTE_FILE
ヘッダーに入れます。FileHeaders.REMOTE_FILE_INFO
ヘッダーは、追加の リモートファイル情報を提供します (デフォルトでは JSON で表されます)。SmbStreamingMessageSource
の fileInfoJson
プロパティを false
に設定すると、ヘッダーに SmbFileInfo
オブジェクトが含まれます。
Java 構成を使用した構成
次の Spring Boot アプリケーションは、Java 構成で受信アダプターを構成する方法の例を示しています。
@SpringBootApplication
public class SmbJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(SmbJavaApplication.class)
.web(false)
.run(args);
}
@Bean
@InboundChannelAdapter(channel = "stream")
public MessageSource<InputStream> smbMessageSource() {
SmbStreamingMessageSource messageSource = new SmbStreamingMessageSource(template());
messageSource.setRemoteDirectory("smbSource/");
messageSource.setFilter(new AcceptAllFileListFilter<>());
messageSource.setMaxFetchSize(1);
return messageSource;
}
@Bean
@Transformer(inputChannel = "stream", outputChannel = "data")
public org.springframework.integration.transformer.Transformer transformer() {
return new StreamTransformer("UTF-8");
}
@Bean
public SmbRemoteFileTemplate template() {
return new SmbRemoteFileTemplate(smbSessionFactory());
}
@ServiceActivator(inputChannel = "data", adviceChain = "after")
@Bean
public MessageHandler handle() {
return System.out::println;
}
@Bean
public ExpressionEvaluatingRequestHandlerAdvice after() {
ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
advice.setOnSuccessExpression(
"@template.remove(headers['file_remoteDirectory'] + headers['file_remoteFile'])");
advice.setPropagateEvaluationFailures(true);
return advice;
}
}
この例では、トランスフォーマーの下流にあるメッセージハンドラーに、処理後に リモートファイルを削除する advice
があることに注意してください。
受信チャネルアダプター: リモートファイルフェッチの制御
受信チャネルアダプターを構成するときに考慮する必要がある 2 つのプロパティがあります。max-messages-per-poll
は、すべてのポーラーと同様に、各ポーリングで発行されるメッセージの数を制限するために使用できます (構成された値よりも多くの準備ができている場合)。max-fetch-size
は、リモートサーバーから一度に取得するファイルの数を制限できます。
次のシナリオでは、開始状態が空のローカルディレクトリであると想定しています。
max-messages-per-poll=2
およびmax-fetch-size=1
: アダプターは、1 つのファイルをフェッチし、それを発行し、次のファイルをフェッチし、それを発行してから、次のポーリングまでスリープします。max-messages-per-poll=2
およびmax-fetch-size=2
): アダプターは両方のファイルをフェッチしてから、それぞれを発行します。max-messages-per-poll=2
およびmax-fetch-size=4
: アダプターは最大 4 つのファイル(使用可能な場合)をフェッチし、最初の 2 つ(少なくとも 2 つある場合)を発行します。次の 2 つのファイルは、次のポーリングで発行されます。max-messages-per-poll=2
およびmax-fetch-size
が指定されていない: アダプターは、すべてのリモートファイルをフェッチし、最初の 2 つを発行します(少なくとも 2 つある場合)。後続のファイルは、後続のポーリングで発行されます(一度に 2 つ)。すべてのファイルが消費されると、リモートフェッチが再度試行され、新しいファイルが取得されます。
アプリケーションの複数のインスタンスをデプロイする場合、1 つのインスタンスがすべてのファイルを「取得」し、他のインスタンスを枯渇させないように、小さな max-fetch-size をお勧めします。 |
max-fetch-size
のもう 1 つの用途は、リモートファイルのフェッチを停止したいが、すでにフェッチされているファイルの処理を続行する場合です。MessageSource
で maxFetchSize
プロパティを設定すると(プログラムで、JMX を使用して、または制御バスを使用して)、アダプターがそれ以上のファイルをフェッチするのを効果的に停止しますが、ポーラーは以前にフェッチされたファイルのメッセージを送信し続けます。プロパティが変更されたときにポーラーがアクティブである場合、変更は次のポーリングで有効になります。
シンクロナイザには Comparator<SmbFile>
を提供できます。これは、maxFetchSize
でフェッチされるファイルの数を制限する場合に役立ちます。
SMB 送信チャネルアダプター
ファイルを SMB 共有に書き込む場合、および XML <int-smb:outbound-channel-adapter>
コンポーネントの場合は SmbMessageHandler
を使用します。Java 構成の場合、SmbMessageHandler
を SmbSessionFactory
(または SmbRemoteFileTemplate
) と共に提供する必要があります。
@Bean
@ServiceActivator(inputChannel = "storeToSmbShare")
public MessageHandler smbMessageHandler(SmbSessionFactory smbSessionFactory) {
SmbMessageHandler handler = new SmbMessageHandler(smbSessionFactory);
handler.setRemoteDirectoryExpression(
new LiteralExpression("remote-target-dir"));
handler.setFileNameGenerator(m ->
m.getHeaders().get(FileHeaders.FILENAME, String.class) + ".test");
handler.setAutoCreateDirectory(true);
return handler;
}
Java DSL を使用した構成
次の Spring Boot アプリケーションは、Java DSL を使用して送信アダプターを構成する方法の例を示しています。
@SpringBootApplication
@IntegrationComponentScan
public class SmbJavaApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context =
new SpringApplicationBuilder(SmbJavaApplication.class)
.web(false)
.run(args);
MyGateway gateway = context.getBean(MyGateway.class);
gateway.sendToSmb(new File("/foo/bar.txt"));
}
@Bean
public SmbSessionFactory smbSessionFactory() {
SmbSessionFactory smbSession = new SmbSessionFactory();
smbSession.setHost("myHost");
smbSession.setPort(445);
smbSession.setDomain("myDomain");
smbSession.setUsername("myUser");
smbSession.setPassword("myPassword");
smbSession.setShareAndDir("myShareAndDir");
smbSession.setSmbMinVersion(DialectVersion.SMB210);
smbSession.setSmbMaxVersion(DialectVersion.SMB311);
return smbSession;
}
@Bean
public IntegrationFlow smbOutboundFlow() {
return IntegrationFlow.from("toSmbChannel")
.handle(Smb.outboundAdapter(smbSessionFactory(), FileExistsMode.REPLACE)
.useTemporaryFileName(false)
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
.remoteDirectory("smbTarget")
).get();
}
@MessagingGateway
public interface MyGateway {
@Gateway(requestChannel = "toSmbChannel")
void sendToSmb(File file);
}
}
SMB 送信ゲートウェイ
SMB 送信 ゲートウェイは、リモート SMB サーバーと対話するための限られたコマンドセットを提供します。サポートされているコマンドは次のとおりです。
ls
(リストファイル)nlst
(リストファイル名)get
(ファイルを取得する)mget
(ファイルの取得)rm
(ファイルを削除)mv
(ファイルの移動 / 名前変更)put
(ファイルの送信)mput
(複数のファイルを送信する)
ls
コマンドの使用
ls
はリモートファイルをリストし、次のオプションをサポートします。
-1
: ファイル名のリストを取得します。デフォルトでは、FileInfo
オブジェクトのリストを取得します-a
: すべてのファイルを含める ( "." で始まるものを含む)-f
: リストをソートしないでください-dirs
: インクルードディレクトリ (デフォルトで除外)-links
: シンボリックリンクを含める (デフォルトで除外)-R
: リモートディレクトリを再帰的にリストする
さらに、ファイル名のフィルタリングは inbound-channel-adapter
と同じ方法で提供されます。
ls
操作から生じるメッセージペイロードは、ファイル名のリストまたは FileInfo
オブジェクトのリストです(-1
スイッチを usr するかどうかによって異なります)。これらのオブジェクトは、変更された時間、権限などの情報を提供します。
ls
コマンドが実行されたリモートディレクトリは、file_remoteDirectory
ヘッダーで提供されます。
再帰オプション(-R
)を使用する場合、fileName
にはサブディレクトリ要素が含まれ、ファイルへの相対パス(リモートディレクトリに対する相対パス)を表します。-dirs
オプションを使用する場合、各再帰ディレクトリもリスト内の要素として返されます。この場合、-1
オプションを使用しないことをお勧めします。FileInfo
オブジェクトを使用するとファイルとディレクトリを区別できなくなるためです。
nlst
コマンドの使用
nlst
はリモートファイル名をリストし、1 つのオプションのみをサポートします。
-f
: リストをソートしないでください
nlst
操作から生じるメッセージペイロードは、ファイル名のリストです。
file_remoteDirectory
ヘッダーには、nlst
コマンドが実行されたリモートディレクトリが保持されます。
get
コマンドの使用
get
はリモートファイルを取得し、次のオプションをサポートします。
-P
: リモートファイルのタイムスタンプを保持します。-stream
: リモートファイルをストリームとして取得します。-D
: 転送に成功したら、リモートファイルを削除します。FileExistsMode
はIGNORE
であり、ローカルファイルがすでに存在するため、転送が無視される場合、リモートファイルは削除されません。
file_remoteDirectory
ヘッダーはリモートディレクトリを保持し、file_remoteFile
ヘッダーはファイル名を保持します。
get
操作の結果として得られるメッセージペイロードは、取得されたファイルを表す File
オブジェクトです。-stream
オプションを使用する場合、ペイロードは File
ではなく InputStream
になります。テキストファイルの場合、一般的な使用例は、この操作をファイルスプリッターまたはストリームトランスフォーマーと組み合わせることです。リモートファイルをストリームとして使用する場合、ストリームの使用後に Session
を閉じる必要があります。便宜上、Session
は closeableResource
ヘッダーで提供され、IntegrationMessageHeaderAccessor
は便利なメソッドを提供します。
Closeable closeable = new IntegrationMessageHeaderAccessor(message).getCloseableResource();
if (closeable != null) {
closeable.close();
}
次の例は、ファイルをストリームとして使用する方法を示しています。
<int-smb:outbound-gateway session-factory="smbSessionFactory"
request-channel="inboundGetStream"
command="get"
command-options="-stream"
expression="payload"
remote-directory="smbTarget"
reply-channel="stream" />
<int-file:splitter input-channel="stream" output-channel="lines" />
カスタムコンポーネントで入力ストリームを使用する場合は、Session を閉じる必要があります。次の例に示すように、カスタムコードでそれを行うか、メッセージのコピーを service-activator にルーティングして SpEL を使用できます。 |
<int:service-activator input-channel="closeSession"
expression="headers['closeableResource'].close()" />
mget
コマンドの使用
mget
は、パターンに基づいて複数のリモートファイルを取得し、次のオプションをサポートします。
-P
: リモートファイルのタイムスタンプを保持します。-R
: ディレクトリツリー全体を再帰的に取得します。-x
: パターンに一致するファイルがない場合は例外をスローします(そうでない場合は空のリストが返されます)。-D
: 転送が成功したら、各リモートファイルを削除します。転送が無視された場合、FileExistsMode
はIGNORE
であり、ローカルファイルがすでに存在するため、リモートファイルは削除されません。
mget
操作の結果のメッセージペイロードは、List<File>
オブジェクト(つまり、File
オブジェクトの List
、それぞれが取得したファイルを表す)です。
FileExistsMode が IGNORE の場合、出力メッセージのペイロードには、ファイルがすでに存在するためにフェッチされなかったファイルが含まれなくなりました。以前は、配列には既存のファイルを含むすべてのファイルが含まれていました。 |
使用する式は、リモートパスが で終わる結果を生成する必要があることを決定します。たとえば、
myfiles/
は myfiles
の完全なツリーをフェッチします。
再帰的な MGET
を FileExistsMode.REPLACE_IF_MODIFIED
モードと組み合わせて使用すると、リモートディレクトリツリー全体をローカルで定期的に同期できます。このモードは、-P
(タイムスタンプを保持) オプションに関係なく、ローカルファイルの最終変更タイムスタンプを リモートファイルのタイムスタンプに設定します。
再帰を使用する場合の注意 ( -R ) パターンは無視され、 サブディレクトリをフィルタリングすると、そのサブディレクトリの追加の走査は実行されません。
通常、リモートディレクトリ構造がローカルに保持されるように、 |
永続ファイルリストフィルターにブールプロパティ forRecursion
が追加されました。このプロパティを true
に設定すると、alwaysAcceptDirectories
も設定されます。これは、送信ゲートウェイ(ls
および mget
)での再帰操作が常にディレクトリツリー全体を毎回トラバースすることを意味します。これは、ディレクトリツリーの奥深くで変更が検出されなかった問題を解決するためです。さらに、forRecursion=true
により、ファイルへのフルパスがメタデータストアキーとして使用されます。これにより、同じ名前のファイルが異なるディレクトリに複数回表示された場合にフィルターが正しく機能しなかった問題が解決されます。重要: これは、永続メタデータストア内の既存のキーが、最上位ディレクトリにあるファイルで見つからないことを意味します。このため、プロパティはデフォルトで false
です。これは将来のリリースで変更される可能性があります。
alwaysAcceptDirectorties
を true
に設定することで、常にディレクトリを渡すように SmbSimplePatternFileListFilter
および SmbRegexPatternFileListFilter
を構成できます。これにより、次の例に示すように、単純なパターンの再帰が可能になります。
<bean id="starDotTxtFilter"
class="org.springframework.integration.smb.filters.SmbSimplePatternFileListFilter">
<constructor-arg value="*.txt" />
<property name="alwaysAcceptDirectories" value="true" />
</bean>
<bean id="dotStarDotTxtFilter"
class="org.springframework.integration.smb.filters.SmbRegexPatternFileListFilter">
<constructor-arg value="^.*\.txt$" />
<property name="alwaysAcceptDirectories" value="true" />
</bean>
ゲートウェイで filter
プロパティを使用して、これらのフィルターのいずれかを提供できます。
送信ゲートウェイの部分的な成功 (mget
および mput
) も参照してください。
put
コマンドの使用
put
はファイルをリモートサーバーに送信します。メッセージのペイロードは、java.io.File
、byte[]
、String
にすることができます。remote-filename-generator
(または式)は、リモートファイルに名前を付けるために使用されます。その他の使用可能な属性には、remote-directory
、temporary-remote-directory
、それらに相当する *-expression
(use-temporary-file-name
および auto-create-directory
)が含まれます。詳細については、スキーマのドキュメント [GitHub] (英語) を参照してください。
put
操作から生じるメッセージペイロードは、転送後のサーバー上のファイルの完全パスを含む String
です。
mput
コマンドの使用
mput
は複数のファイルをサーバーに送信し、次のオプションをサポートします。
-R
: 再帰 — ディレクトリとサブディレクトリ内のすべてのファイルを送信します(フィルタリングされている場合もあります)
メッセージペイロードは、ローカルディレクトリを表す java.io.File
(または String
) である必要があります。File
または String
のコレクションもサポートされています。
put
コマンドと同じ属性がサポートされています。さらに、mput-pattern
、mput-regex
、mput-filter
または mput-filter-expression
のいずれかを使用して、ローカルディレクトリ内のファイルをフィルタリングできます。サブディレクトリ自体がフィルターを通過する限り、フィルターは再帰で機能します。フィルターを通過しないサブディレクトリは再帰されません。
mput
操作から生じるメッセージペイロードは、List<String>
オブジェクト(つまり、転送から生じるリモートファイルパスの List
)です。
送信ゲートウェイの部分的な成功 (mget
および mput
) も参照してください。
rm
コマンドの使用
rm
コマンドにはオプションがありません。
削除操作が成功した場合、結果のメッセージペイロードは Boolean.TRUE
です。それ以外の場合、メッセージペイロードは Boolean.FALSE
です。file_remoteDirectory
ヘッダーはリモートディレクトリを保持し、file_remoteFile
ヘッダーはファイル名を保持します。
mv
コマンドの使用
mv
コマンドにはオプションがありません。
expression
属性は "from" パスを定義し、rename-expression
属性は "to" パスを定義します。デフォルトでは、rename-expression
は headers['file_renameTo']
です。この式は、null または空の String
と評価されてはなりません。必要に応じて、必要なリモートディレクトリが作成されます。結果メッセージのペイロードは Boolean.TRUE
です。file_remoteDirectory
ヘッダーは元のリモートディレクトリを保持し、file_remoteFile
ヘッダーはファイル名を保持します。file_renameTo
ヘッダーは新しいパスを保持します。
remoteDirectoryExpression
は、利便性のために mv
コマンドで使用できます。"from" ファイルが完全なファイルパスでない場合、remoteDirectoryExpression
の結果が リモートディレクトリとして使用されます。たとえば、あるディレクトリ内の リモートファイルの名前を変更するだけのタスクの場合、"to" ファイルにも同じことが当てはまります。
追加のコマンド情報
get
および mget
コマンドは、local-filename-generator-expression
属性をサポートしています。転送中にローカルファイルの名前を生成する SpEL 式を定義します。評価コンテキストのルートオブジェクトはリクエストメッセージです。remoteFileName
変数も使用できます。mget
で特に役立ちます(例: local-filename-generator-expression="#remoteFileName.toUpperCase() + headers.foo"
)。
get
および mget
コマンドは、local-directory-expression
属性をサポートしています。転送中にローカルディレクトリの名前を生成する SpEL 式を定義します。評価コンテキストのルートオブジェクトはリクエストメッセージです。remoteDirectory
変数も使用できます。mget で特に役立ちます(例: local-directory-expression="'/tmp/local/' + #remoteDirectory.toUpperCase() + headers.myheader"
)。この属性は、local-directory
属性と相互に排他的です。
すべてのコマンドについて、ゲートウェイの「式」プロパティは、コマンドが動作するパスを保持します。mget
コマンドの場合、式は に評価される場合があります。これは、すべてのファイル
somedirectory/
、および *
で終わるその他の値を取得することを意味します。
次の例は、ls
コマンド用に構成されたゲートウェイを示しています。
<int-smb:outbound-gateway id="gateway1"
session-factory="smbSessionFactory"
request-channel="inbound1"
command="ls"
command-options="-1"
expression="payload"
reply-channel="toSplitter"/>
toSplitter
チャネルに送信されるメッセージのペイロードは、String
オブジェクトのリストであり、各オブジェクトにはファイルの名前が含まれています。command-options="-1"
を省略した場合、ペイロードは FileInfo
オブジェクトのリストになります。オプションをスペース区切りリストとして提供できます(例: command-options="-1 -dirs -links"
)。
GET
、MGET
、PUT
、MPUT
コマンドは、FileExistsMode
プロパティ (ネームスペースサポートを使用する場合は mode
) をサポートします。これは、ローカルファイルが存在する場合 (GET
および MGET
) または リモートファイルが存在する場合 (PUT
および MPUT
) の動作に影響します。サポートされているモードは REPLACE
、APPEND
、FAIL
、IGNORE
です。下位互換性のために、PUT
および MPUT
操作のデフォルトモードは REPLACE
です。GET
および MGET
操作の場合、デフォルトは FAIL
です。
Java 構成を使用した構成
次の Spring Boot アプリケーションは、Java 構成で送信ゲートウェイを構成する方法の例を示しています。
@SpringBootApplication
public class SmbJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(SmbJavaApplication.class)
.web(false)
.run(args);
}
@Bean
public SmbSessionFactory smbSessionFactory() {
SmbSessionFactory smbSession = new SmbSessionFactory();
smbSession.setHost("myHost");
smbSession.setPort(445);
smbSession.setDomain("myDomain");
smbSession.setUsername("myUser");
smbSession.setPassword("myPassword");
smbSession.setShareAndDir("myShareAndDir");
smbSession.setSmbMinVersion(DialectVersion.SMB210);
smbSession.setSmbMaxVersion(DialectVersion.SMB311);
return smbSession;
}
@Bean
@ServiceActivator(inputChannel = "smbChannel")
public MessageHandler handler() {
SmbOutboundGateway smbOutboundGateway =
new SmbOutboundGateway(smbSessionFactory(), "'my_remote_dir/'");
smbOutboundGateway.setOutputChannelName("replyChannel");
return smbOutboundGateway;
}
}
Java DSL を使用した構成
次の Spring Boot アプリケーションは、送信ゲートウェイを Java DSL で構成する方法の例を示しています。
@SpringBootApplication
public class SmbJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(SmbJavaApplication.class)
.web(false)
.run(args);
}
@Bean
public SmbSessionFactory smbSessionFactory() {
SmbSessionFactory smbSession = new SmbSessionFactory();
smbSession.setHost("myHost");
smbSession.setPort(445);
smbSession.setDomain("myDomain");
smbSession.setUsername("myUser");
smbSession.setPassword("myPassword");
smbSession.setShareAndDir("myShareAndDir");
smbSession.setSmbMinVersion(DialectVersion.SMB210);
smbSession.setSmbMaxVersion(DialectVersion.SMB311);
return smbSession;
}
@Bean
public SmbOutboundGatewaySpec smbOutboundGateway() {
return Smb.outboundGateway(smbSessionFactory(),
AbstractRemoteFileOutboundGateway.Command.MGET, "payload")
.options(AbstractRemoteFileOutboundGateway.Option.RECURSIVE)
.regexFileNameFilter("(subSmbSource|.*.txt)")
.localDirectoryExpression("'localDirectory/' + #remoteDirectory")
.localFilenameExpression("#remoteFileName.replaceFirst('smbSource', 'localTarget')");
}
@Bean
public IntegrationFlow smbFlow(AbstractRemoteFileOutboundGateway<SmbFile> smbOutboundGateway) {
return f -> f
.handle(smbOutboundGateway)
.channel(c -> c.queue("remoteFileOutputChannel"));
}
}
送信ゲートウェイの部分的な成功 (mget
および mput
)
( mget
および mput
を使用して) 複数のファイルに対して操作を実行すると、1 つ以上のファイルが転送された後、しばらくして例外が発生する可能性があります。この場合、PartialSuccessException
がスローされます。通常の MessagingException
プロパティ (failedMessage
および cause
) と同様に、この例外には 2 つの追加プロパティがあります。
partialResults
: 正常な転送結果。derivedInput
: リクエストメッセージから生成されたファイルのリスト(mput
用に転送するローカルファイルなど)。
これらの属性により、正常に転送されたファイルと転送されなかったファイルを判別できます。
再帰的な mput
の場合、PartialSuccessException
にはネストされた PartialSuccessException
インスタンスがあります。
次のディレクトリ構造を考慮してください。
root/
|- file1.txt
|- subdir/
| - file2.txt
| - file3.txt
|- zoo.txt
file3.txt
で例外が発生した場合、ゲートウェイによってスローされた PartialSuccessException
には、file1.txt
、subdir
、zoo.txt
の derivedInput
と file1.txt
の partialResults
があります。その cause
は、file2.txt
の derivedInput
と file2.txt
の file3.txt
および partialResults
を備えた別の PartialSuccessException
です。
リモートファイル情報
SmbStreamingMessageSource
( SMB ストリーミング受信チャネルアダプター )、SmbInboundFileSynchronizingMessageSource
( SMB 受信チャネルアダプター )、および SmbOutboundGateway
( SMB 送信ゲートウェイ ) の「読み取り」-commands は、メッセージに追加のヘッダーを提供し、リモートファイルに関する情報を生成します。
FileHeaders.REMOTE_HOST_PORT
- ファイル転送操作中にリモートセッションが接続された host:port ペア。FileHeaders.REMOTE_DIRECTORY
- 操作が実行されたリモートディレクトリ。FileHeaders.REMOTE_FILE
- リモートファイル名。単一ファイル操作にのみ適用されます。
SmbInboundFileSynchronizingMessageSource
は リモートファイルに対してメッセージを生成しませんが、ローカルコピーを使用するため、AbstractInboundFileSynchronizer
は リモートファイルに関する情報を、同期操作中に URI スタイル (protocol://host:port/remoteDirectory#remoteFileName
) で MetadataStore
(外部で構成可能) に保存します。このメタデータは、ローカルファイルがポーリングされるときに SmbInboundFileSynchronizingMessageSource
によって取得されます。ローカルファイルが削除されたら、そのメタデータエントリを削除することをお勧めします。AbstractInboundFileSynchronizer
は、この目的のために removeRemoteFileMetadata()
コールバックを提供します。さらに、メタデータキーで使用される setMetadataStorePrefix()
があります。同じ MetadataStore
インスタンスがこれらのコンポーネント間で共有されている場合、フィルターと AbstractInboundFileSynchronizer
の両方がメタデータエントリに同じローカルファイル名を使用するため、エントリのオーバーライドを回避するために、このプレフィックスを MetadataStore
ベースの FileListFilter
実装で使用されるものとは異なるものにすることをお勧めします。鍵。