Spring Integration - 入站文件端点。如何正确处理文件。

时间:2016-03-03 14:37:21

标签: java spring file integration spring-integration

我有一个Spring集成流程如下。

<int-file:inbound-channel-adapter id="filesIn"
        directory="file:${incomingDir}" 
        filename-pattern="*.txt" 
        prevent-duplicates="true">
    <int:poller id="poller" fixed-delay="5000"/>
    </int-file:inbound-channel-adapter>

    <int:splitter input-channel="filesIn" 
        ref="filesSplitterService"
        method="splitFilesToReportContent"
        output-channel="reportProcessIn"
     />

     <int:channel id="reportProcessIn"/>

     <int:chain input-channel="reportProcessIn" output-channel="reportProcessOut">    
        <int:service-activator ref="reportProcessorService" method="readReportMetaData" />
        <int:service-activator ref="reportProcessorService" method="saveReportFileInFileSystem" />
        <int:service-activator ref="reportProcessorService" method="saveReportMetaDataInDB" />
    </int:chain>

     <int:channel id="reportProcessOut"/>


    <bean id="filesSplitterService" class="com.app.integration.FilesSplitter"/>

    <bean id="reportProcessorService" class="com.app.reporting.integration.ReportProcessor"/>

传入文件由一个服务拆分,并创建一个 ReportContent 列表。

然后服务链获取 ReportContent 的每个元素,并从文件内容(如报告ID,报告类型)处理read_report_meta_data,将报告内容字符串保存到相应目录中的文件,并将报表元数据保存在数据库中。流量工作正常,但似乎有一个松散的结束。

我收到以下异常。

  

org.springframework.integration.MessageDeliveryException:Dispatcher   没有订阅者

  1. 我不需要聚合分割元素。在数据库中保存元数据后,就我而言,流程已完成。

  2. 但是我想在处理之后将原始文件(我分割成报告文件的主文件)移动到其他目录。我怎么能把这个逻辑融入其中?文件:出站通道似乎是这样做的方式,但我不明白如何做。

  3. 有没有办法根据readReportMetaData操作中读取的一些元数据来避免saveReportFileInSystem和saveReportMetaDataInDB操作。

  4. 为方便起见,我在下面给出了服务类的结构。

    class:FilesSplitter

    public List<ReportContent> splitFilesToReportContent(File file){
    } 
    

    类:ReportProcessor

    public ReportContent readReportMetaData(ReportContent reportContent) {
    
    
    }
    
    
    
    public ReportContent saveReportFileInFileSystem(ReportContent reportContent) {
    
    
        }
    
    public ReportContent saveReportMetaDataInDB(ReportContent reportContent) {
    
    
        }
    

    需要注意的一点是我没有使用邮件标题。我还没有觉得有必要使用,但我可以使用。我是Spring集成的新手,因此,任何改进此流程的建议都会有所帮助。

2 个答案:

答案 0 :(得分:3)

<强> 1。我收到以下异常... org.springframework.integration.MessageDeliveryException

我想你在这里错过了file:outbound-channel-adapter的定义。

<强> 2。但是我想在处理之后将原始文件(我分割成报告文件的主文件)移动到其他目录。我怎么能加入那个逻辑?

正如14.3.4 File Outbound Channel Adapter中所述,您应该使用delete-source-files的{​​{1}}属性,但是(!)

  

...属性仅在入站消息具有文件有效内容或FileHeaders.ORIGINAL_FILE标头值包含源文件实例或表示原始文件路径的字符串时才有效。

所以,在你outbound-channel-adapter中你应该处理原始消息。您不再拥有源文件作为有效负载。因此,只有一个选项是正确设置reportProcessorService标头值。

第3。有没有办法根据readReportMetaData操作中读取的一些元数据来避免saveReportFileInSystem和saveReportMetaDataInDB操作?

是的,有。在EIP链中的FileHeaders.ORIGINAL_FILE之后使用PayloadTypeRouter(如果可能的话,那么简单)或Configuring (Generic) Router

答案 1 :(得分:3)

我们通常Dispatcher has no subscribersSubscribableChannel没有订阅者(就像你的reportProcessOut)或者那些订阅者已被停止时,可以视为“没有订阅者”,太

如果您对该结果不感兴趣,我们通常建议您将<service-activator>结果发送到nullChannel。如果您无法使用标准的单向组件<outbound-channel-adapter>来完成任务,那就是这种情况。

  

但是我想移动原始文件,即我分割成报告文件的主文件,

您可以使用<publish-subscriber-channel>的第二个单向订阅者作为filesIn。并且使用标准File.renameTo()功能实现了这一目标。我没有理由用<int-file:outbound-channel-adapter>之类的东西来打扰你。您已经在文件系统上了。所以,只需使用它的功能。当我们处理FTP,SFTP等远程文件时,我们需要文件适配器。

您可以使用Map<String, Object> headers作为3服务方法的第二个参数,Framework将从请求Message<?>为您注入适当的对象。

请参阅@Andriy Kryvtsun关于“避免saveReportFileInSystem”的回答。

作为替代方案,您可以使用<filter>来跳过和删除因某些原因无法保存的邮件。