Spring integration Spring集成:如何按顺序处理文件

Spring integration Spring集成:如何按顺序处理文件,spring-integration,Spring Integration,我使用“int file:inbound channel adapter”将存在的文件加载到目录中。我喜欢按顺序处理文件:这意味着当第一个文件的处理完成时,我加载第二个文件…等等 我看到一个文件,但我不能预测处理一个文件所需的时间,这取决于文件的大小 我的源代码: <int-file:inbound-channel-adapter directory="${directory.files.local}" id="filesIn" channel="channel.files

我使用“int file:inbound channel adapter”将存在的文件加载到目录中。我喜欢按顺序处理文件:这意味着当第一个文件的处理完成时,我加载第二个文件…等等

我看到一个文件,但我不能预测处理一个文件所需的时间,这取决于文件的大小

我的源代码:

    <int-file:inbound-channel-adapter
    directory="${directory.files.local}" id="filesIn" channel="channel.filesIn">
    <int:poller fixed-delay="1000" max-messages-per-poll="1" />

</int-file:inbound-channel-adapter>

文件的处理过程是file:inbound channel adapter-->transformer-->splitter-->http:outbound gateway-->outbound mail adapter-->文件的处理已完成,因此此时,我将选择下一个要处理的文件

我的项目配置太复杂了。 下面,我将向您展示更多配置: 配置的第一部分是:

<int-sftp:inbound-channel-adapter id="sftpInbondAdapter"
    auto-startup="true" channel="receiveChannel" session-factory="sftpSessionFactory"
    local-directory="file:${directory.files.local}" remote-directory="${directory.files.remote}"
    auto-create-local-directory="true" delete-remote-files="true"
    filename-regex=".*\.txt$">
    <int:poller fixed-delay="${sftp.interval.request}"
        max-messages-per-poll="-1" />
</int-sftp:inbound-channel-adapter>
<!-- <int:poller cron="0 * 17 * * ?"></int:poller> -->

<int-file:inbound-channel-adapter
    filter="compositeFileFilter" directory="${directory.files.local}" id="filesIn"
    channel="channel.filesIn" prevent-duplicates="true">
    <int:poller fixed-delay="1000" max-messages-per-poll="1" />
</int-file:inbound-channel-adapter>

<int:transformer input-channel="channel.filesIn"
    output-channel="channel.file.router" ref="fileTransformer" method="transform" />

<int:recipient-list-router id="fileRouter"
    input-channel="channel.file.router">

    <int:recipient channel="channel.empty.files"
        selector-expression="payload.length()==0" />
    <int:recipient channel="channel.filesRejected"
        selector-expression="payload.toString().contains('rejected')" />
    <int:recipient channel="toSplitter"
        selector-expression="(payload.length()>0) and(!payload.toString().contains('rejected'))" />

</int:recipient-list-router>

然后,我的程序从channel ToSpliter中逐行读取文件:

    <int-file:splitter input-channel="toSplitter"
    output-channel="router" requires-reply="false" />

<int:recipient-list-router id="recipentRouter"
    input-channel="router">

    <int:recipient channel="channelA"
        selector-expression="headers['file_name'].startsWith('${filenameA.prefix}')" />

    <int:recipient channel="channelB"
        selector-expression="headers['file_name'].startsWith('${filenameB.prefix}')" />

</int:recipient-list-router>

每个通道A和B应为每条线路调用两个不同的WS。 对于文件A,对ws-code的每个文件使用异步调用如下所示:

<int:header-enricher input-channel="channelA"
    output-channel="channelA.withHeader">
    <int:header name="content-type" value="application/json" />
    <int:header name="key1" expression="payload.split('${line.column.separator}')[0]" />
    <int:header name="key2" expression="payload"></int:header>
</int:header-enricher>

<int:transformer input-channel="channelA.withHeader"
    output-channel="channelA.request" ref="imsiMsgTransformer"
    method="transform">
</int:transformer>


<int:channel id="channelA.request">
    <int:queue capacity="10" />



在每个激活器(回复通道和恢复通道)中,我计算文件的进程,直到文件完成为止。此时,我应加载第二个文件A2或文件B…等,这是默认行为,只要

  • 轮询器没有任务执行器(您没有)
  • 适配器下游仅使用
    DirectChannel
    s(默认值)-这意味着没有
    QueueChannel
    s或
    ExecutorChannel
    (即通道上没有
    task executor
  • 在这种情况下,在当前轮询完成之前,甚至不会考虑下一次轮询-流在轮询器线程上运行,一次只能进行一次轮询

    固定延迟
    在当前文件完成处理之前不会启动

    编辑

    如果需要在流上使用异步处理,则需要使用或简单

    您将提供一个
    PollSkipStrategy
    实现,该实现将返回false,直到文件完成

    这样,后续的投票将被跳过,直到您做出决定

    EDIT2

    像这样的

    /*
     * Copyright 2015 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    package org.springframework.integration.scheduling;
    
    /**
     * @author Gary Russell
     * @since 4.3
     *
     */
    public class SimplePollSkipStrategy implements PollSkipStrategy {
    
        private volatile boolean skip;
    
        @Override
        public boolean skipPoll() {
            return this.skip;
        }
    
        public void skipPolls() {
            this.skip = true;
        }
    
        public void reset() {
            this.skip = false;
        }
    }
    
    • 将其作为
      添加到您的上下文中
    • 使用
      PollSkipAdvice
    • 如果要跳过轮询,请调用
      skipPolls()
    • 处理完文件后,请调用
      reset()

    正如我所说的,只要所有频道都是默认的
    DirectChannel
    ,下一次轮询就不会发生,直到邮件发送后1秒。我有一个问题,那就是,出于某种原因,我使用了队列和任务执行器:例如,对于每行文件,我应该调用2个WS,以加速处理一个文件,http出站网关应在队列通道上使用任务执行器。结果是:调用ws时第一个文件没有完成,第二个文件被加载并开始处理谢谢Gary。但是你能给我举个例子吗?首先,你需要一些机制来“知道”文件何时被完全处理。你怎么知道的?也许您可以展示更多的配置。我的问题是,下游异步流如何知道最后一条记录何时被处理。你能在最后一条信息上设置一个标题吗?然后我可以指引你。
    /*
     * Copyright 2015 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    package org.springframework.integration.scheduling;
    
    /**
     * @author Gary Russell
     * @since 4.3
     *
     */
    public class SimplePollSkipStrategy implements PollSkipStrategy {
    
        private volatile boolean skip;
    
        @Override
        public boolean skipPoll() {
            return this.skip;
        }
    
        public void skipPolls() {
            this.skip = true;
        }
    
        public void reset() {
            this.skip = false;
        }
    }