此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.4.4! |
SMB 支持
Spring 集成支持使用 SMB 进行文件传输作。
服务器消息块 (SMB) 是一种简单的网络协议,可用于将文件传输到共享文件服务器。
您需要将此依赖项包含在您的项目中:
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-smb</artifactId>
<version>6.3.10-SNAPSHOT</version>
</dependency>
compile "org.springframework.integration:spring-integration-smb:6.3.10-SNAPSHOT"
概述
Java CIFS 客户端库已被选为 CIFS/SMB 网络协议的 Java 实现。
其SmbFile
abstraction 被简单地包装到 Spring Integration的“远程文件”基础中,例如SmbSession
,SmbRemoteFileTemplate
等。
SMB 通道适配器和支持类的实现与 (S)FTP 或 AWS S3 协议的现有组件完全相似。 因此,如果您熟悉这些组件,那么它很容易使用。
Spring 集成通过提供三个客户端端点来支持通过 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
公开选项以使用 Min/Max 版本设置 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
.
必须在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
。
它是AbstractInboundFileSynchronizingMessageSource
这需要SmbInboundFileSynchronizer
注射。
对于过滤远程文件,您仍然可以使用任何现有的FileListFilter
implementations 实现,但特别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 开始,您可以使用上次修改策略筛选 SMB 文件SmbLastModifiedFileListFilter
.
此过滤器可以使用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 流式处理入站频道适配器
此适配器生成 payload 类型的 messageInputStream
,允许获取文件而不写入本地文件系统。
由于会话保持打开状态,因此使用应用程序负责在使用文件时关闭会话。
该会话在closeableResource
标头 (IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE
).
标准框架组件(例如FileSplitter
和StreamTransformer
,则会自动关闭会话。
有关这些组件的更多信息,请参见File Splitter 和 Stream Transformer。
以下示例说明如何配置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
是允许的。
这SmbStreamingMessageSource
适配器可防止远程文件重复SmbPersistentAcceptOnceFileListFilter
基于 In-MemorySimpleMetadataStore
.
默认情况下,此过滤器也与文件名模式(或 regex)一起应用。
如果需要允许重复项,可以使用AcceptAllFileListFilter
.
任何其他用例都可以由CompositeFileListFilter
(或ChainFileListFilter
).
Java 配置(本文档后面部分)显示了一种在处理后删除远程文件以避免重复的技术。
有关SmbPersistentAcceptOnceFileListFilter
及其使用方式,请参阅远程持久性文件列表过滤器。
使用max-fetch-size
属性来限制在需要提取时每次轮询时提取的文件数。
将其设置为1
并在集群环境中运行时使用持久性过滤器。
有关更多信息,请参见入站通道适配器:控制远程文件获取。
适配器将远程目录和文件名放在FileHeaders.REMOTE_DIRECTORY
和FileHeaders.REMOTE_FILE
标头。
这FileHeaders.REMOTE_FILE_INFO
header 提供额外的远程文件信息(默认以 JSON 表示)。
如果将fileInfoJson
属性SmbStreamingMessageSource
自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
,这将在处理后删除远程文件。
入站通道适配器:控制远程文件获取
在配置入站通道适配器时,应考虑两个属性。max-messages-per-poll
与所有 Poller 一样,可用于限制每次轮询时发出的消息数(如果已准备好超过配置的值)。max-fetch-size
可以限制一次从远程服务器检索的文件数。
以下场景假定起始状态为空的本地目录:
-
max-messages-per-poll=2
和max-fetch-size=1
:适配器获取一个文件,发出它,获取下一个文件,发出它,然后休眠直到下一次轮询。 -
max-messages-per-poll=2
和max-fetch-size=2
):适配器获取这两个文件,然后发出每个文件。 -
max-messages-per-poll=2
和max-fetch-size=4
:适配器最多获取四个文件(如果可用)并发出前两个文件(如果至少有两个)。 接下来的两个文件将在下一次轮询时发出。 -
max-messages-per-poll=2
和max-fetch-size
未指定:适配器获取所有远程文件并发出前两个文件(如果至少有两个)。 后续文件将在后续轮询时发出(一次两个)。 当所有文件都被消耗时,将再次尝试远程获取以获取任何新文件。
当您部署应用程序的多个实例时,我们建议使用小型max-fetch-size ,以避免一个实例“抓取”所有文件并耗尽其他实例。 |
另一个用途max-fetch-size
是要停止获取远程文件,但继续处理已获取的文件。
设置maxFetchSize
属性MessageSource
(以编程方式,使用 JMX 或控制总线)有效地阻止适配器获取更多文件,但允许 Poller 继续为以前获取的文件发出消息。
如果在更改属性时 poller 处于活动状态,则更改将在下一次轮询时生效。
同步器可以配备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
operation 是文件名列表或FileInfo
对象(取决于您是否使用-1
switch) 的
这些对象提供修改时间、权限等信息。
远程目录ls
执行 action on 的命令在file_remoteDirectory
页眉。
当使用递归选项 (-R
)、fileName
包含任何 subdirectory 元素,并表示文件的相对路径(相对于远程目录)。
如果您使用-dirs
选项,则每个递归目录也会作为列表中的一个元素返回。
在这种情况下,我们建议您不要使用-1
选项,因为您无法区分文件和目录,而使用FileInfo
对象。
用nlst
命令
nlst
列出远程文件名,并且仅支持一个选项:
-
-f
:不对列表进行排序
由nlst
operation 是文件名列表。
这file_remoteDirectory
header 包含远程目录,其中nlst
命令起作用。
使用get
命令
get
检索远程文件并支持以下选项:
-
-P
:保留远程文件的时间戳。 -
-stream
: Retrieve the remote file as a stream. -
-D
: Delete the remote file after successful transfer. The remote file is not deleted if the transfer is ignored, because theFileExistsMode
是IGNORE
并且本地文件已存在。
这file_remoteDirectory
header 包含远程目录,而file_remoteFile
header holds the filename.
由get
作是File
object representing the retrieved file.
If you use the -stream
option, the payload is an InputStream
rather than a File
.
For text files, a common use case is to combine this operation with a file splitter or a stream transformer.
When consuming remote files as streams, you are responsible for closing the Session
after the stream is consumed.
For convenience, the Session
is provided in the closeableResource
header, and IntegrationMessageHeaderAccessor
offers convenience method:
Closeable closeable = new IntegrationMessageHeaderAccessor(message).getCloseableResource();
if (closeable != null) {
closeable.close();
}
Framework components, such as the File Splitter and Stream Transformer, automatically close the session after the data is transferred.
The following example shows how to consume a file as a stream:
<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>
object(即List
之File
对象,每个对象代表一个检索到的文件)。
If the FileExistsMode 是IGNORE ,则输出消息的有效负载不再包含由于文件已存在而未获取的文件。
以前,该数组包含所有文件,包括已存在的文件。 |
The expression you use determine the remote path should produce a result that ends with for example
myfiles/
在myfiles
.
You can use a recursive MGET
与FileExistsMode.REPLACE_IF_MODIFIED
模式,以定期在本地同步整个远程目录树。
此模式将本地文件的上次修改时间戳设置为远程文件的时间戳,而不管-P
(保留时间戳)选项。
使用递归时的注意事项 (
-R )该模式将被忽略并被假定。
默认情况下,将检索整个远程树。
但是,您可以通过提供 如果筛选一个子目录,则不会对该子目录执行额外的遍历。 这 通常,您会使用 |
持久文件列表过滤器现在具有布尔属性forRecursion
.
将此属性设置为true
,还会设置alwaysAcceptDirectories
,这意味着出站网关 (ls
和mget
) 现在每次都始终遍历完整的目录树。
这是为了解决未检测到目录树深处更改的问题。
另外forRecursion=true
使文件的完整路径用作元数据存储键;这解决了以下问题:如果具有相同名称的文件在不同目录中多次出现,则过滤器无法正常工作。
重要说明:这意味着对于顶级目录下的文件,将无法找到持久性元数据存储中的现有键。
因此,该属性为false
默认情况下;这可能会在未来版本中更改。
You can configure the SmbSimplePatternFileListFilter
和SmbRegexPatternFileListFilter
始终传递目录,方法是将alwaysAcceptDirectorties
自true
.
这样做允许对简单模式进行递归,如下例所示:
<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
(或 expression) 用于命名远程文件。
其他可用属性包括remote-directory
,temporary-remote-directory
及其*-expression
等价物:use-temporary-file-name
和auto-create-directory
.
有关更多信息,请参阅 schema documentation.
由put
作是String
,其中包含传输后服务器上文件的完整路径。
使用mput
命令
mput
将多个文件发送到服务器并支持以下选项:
-
-R
: Recursive — 发送目录和子目录中的所有文件(可能已过滤)
消息负载必须是java.io.File
(或String
) that represents a local directory.
A collection of File
或String
也受支持。
与put
命令受支持。
此外,您可以使用mput-pattern
,mput-regex
,mput-filter
或mput-filter-expression
.
只要子目录本身通过过滤器,过滤器就可以使用递归。
未通过过滤器的子目录不会递归。
由mput
作是List<String>
object(即List
传输产生的远程文件路径)。
另请参阅出站网关部分成功 (mget
和mput
).
使用rm
命令
这rm
命令中没有选项。
如果 remove作成功,则生成的消息有效负载为Boolean.TRUE
.
否则,消息负载为Boolean.FALSE
.
这file_remoteDirectory
header 包含远程目录,而file_remoteFile
header 保存文件名。
使用mv
命令
这mv
命令中没有选项。
这expression
属性定义 “from” 路径,而rename-expression
attribute 定义 “to” 路径。
默认情况下,rename-expression
是headers['file_renameTo']
.
此表达式的计算结果不得为 null 或空String
.
如有必要,将创建所需的任何远程目录。
结果消息的有效负载为Boolean.TRUE
.
这file_remoteDirectory
header 包含原始远程目录,而file_remoteFile
header 包含文件名。
这file_renameTo
header 包含新路径。
这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
属性。
对于所有命令,网关的 'expression' 属性保存命令作的路径。
对于mget
command, the expression might evaluate to , meaning to retrieve all files,
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
channel 是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
operations 为REPLACE
.
为GET
和MGET
作,默认值为FAIL
.
使用 Java 配置进行配置
The following Spring Boot application shows an example of how to configure the outbound gateway with Java configuration:
@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
) an exception can occur some time after one or more files have been transferred.
In this case a PartialSuccessException
被抛出。
和往常一样MessagingException
属性 (failedMessage
和cause
),则此异常具有两个附加属性:
-
partialResults
: The successful transfer results. -
derivedInput
: The list of files generated from the request message (such as local files to transfer for anmput
).
These attributes let you determine which files were successfully transferred and which were not.
In the case of a recursive mput
, the PartialSuccessException
may have nested PartialSuccessException
instances.
Consider the following directory structure:
root/
|- file1.txt
|- subdir/
| - file2.txt
| - file3.txt
|- zoo.txt
If the exception occurs on file3.txt
, the PartialSuccessException
thrown by the gateway has derivedInput
之file1.txt
,subdir
和zoo.txt
和partialResults
之file1.txt
.
Its cause
is another PartialSuccessException
with derivedInput
之file2.txt
和file3.txt
和partialResults
之file2.txt
.
远程文件信息
这SmbStreamingMessageSource
(SMB Streaming Inbound Channel Adapter), SmbInboundFileSynchronizingMessageSource
(SMB Inbound Channel Adapter) and "read"-commands of the SmbOutboundGateway
(SMB Outbound Gateway) provide additional headers in the message to produce with an information about the remote file:
-
FileHeaders.REMOTE_HOST_PORT
- 远程会话在文件传输作期间连接到的 host:port 对; -
FileHeaders.REMOTE_DIRECTORY
- 已执行作的远程目录; -
FileHeaders.REMOTE_FILE
- 远程文件名;仅适用于单个文件作。
由于SmbInboundFileSynchronizingMessageSource
不会针对远程文件生成消息,但使用本地副本,AbstractInboundFileSynchronizer
将有关远程文件的信息存储在MetadataStore
(可在外部配置)在 URI 样式 (protocol://host:port/remoteDirectory#remoteFileName
) 进行同步作。
此元数据由SmbInboundFileSynchronizingMessageSource
轮询本地文件时。
删除本地文件时,建议删除其元数据条目。
这AbstractInboundFileSynchronizer
提供removeRemoteFileMetadata()
callback 来实现此目的。
此外,还有一个setMetadataStorePrefix()
用于元数据键。
建议将此前缀与MetadataStore
-基于FileListFilter
implementations,当相同的MetadataStore
instance 在这些组件之间共享,以避免条目覆盖,因为 filter 和AbstractInboundFileSynchronizer
对元数据条目键使用相同的本地文件名。