2016-03-03 72 views
3

我有一个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的每个元素的作品对他们从文件的内容(如报告编号,报告类型)read_report_meta_data,保存内容字符串报告在适当的目录中的文件,并保存报表元数据库中的数据。流程运行良好,除了似乎有一个松散的结局。

我收到以下异常。

org.springframework.integration.MessageDeliveryException:调度 没有订户

  1. 我不需要聚集分裂元素。在将元数据保存到数据库后,就我所关注的流程完成。

  2. 但是我想在使用它之后将原始文件,即我分割成报告文件的主文件移动到其他目录。我怎么能把这个逻辑结合起来?文件:出站渠道似乎是这样做的方式,但我不明白如何。

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

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

类:FilesSplitter

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

类:ReportProcessor

public ReportContent readReportMetaData(ReportContent reportContent) { 


} 



public ReportContent saveReportFileInFileSystem(ReportContent reportContent) { 


    } 

public ReportContent saveReportMetaDataInDB(ReportContent reportContent) { 


    } 

有一点要注意的是,我不使用邮件头。我还没有觉得有必要使用,但我可以使用。我对Spring集成很陌生,所以任何改善这种流程的建议都会有所帮助。

回答

3

1.我得到下面的异常... org.springframework.integration.MessageDeliveryException

我想你在这里漏掉file:outbound-channel-adapter定义。

2.然而,我想将原始文件(我将其分割成报告文件的主文件)移动到其他目录后使用它。我怎么能把这个逻辑结合起来?

写在14.3.4 File Outbound Channel Adapter你应该使用delete-source-files属性为outbound-channel-adapter但是(!)

...属性只会在入站消息具有文件有效负载或者FileHeaders.ORIGINAL_FILE头值包含源文件实例或表示原始文件路径的字符串时起作用。

因此,在你reportProcessorService你应该处理原始信息。您不再有源文件作为有效载荷。因此,只有一个选项是正确设置FileHeaders.ORIGINAL_FILE标题值。

3.有没有办法避免saveReportFileInSystem和saveReportMetaDataInDB操作基于readReportMetaData操作中读取的一些元数据?

是的,有。 readReportMetaData后使用链EIP要么PayloadTypeRouter(如果可能的话becorse其简单)或Configuring (Generic) Router

+1

嗯,我不能投票回答两次:-) –

3

我们通常Dispatcher has no subscribers当有真正为SubscribableChannel没有订户(像你reportProcessOut)或那些订户已停止,它可以也视为“无订户”。

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

不过,我想移动的原始文件,主文件I分裂成报告文件,

你可以做到这一点为<publish-subscriber-channel>filesIn第二单向用户。并具有标准File.renameTo()功能的成就者。我不打算用<int-file:outbound-channel-adapter>之类的东西来打动你的思想。您已经在文件系统上。所以,只要使用它的功能即可。当我们处理FTP,SFTP等远程文件时,我们需要适配器来存储文件。

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

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

作为一种替代方法,您可以使用<filter>来跳过和丢弃不应该由于某种原因保存的消息。

+0

有趣......是'nullChannel'预定义的频道名称? –

+2

是的。参见'DefaultConfiguringBeanFactoryPostProcessor.registerNullChannel()' –

+1

http://docs.spring.io/spring-integration/reference/html/messaging-channels-section.html#channel-special-channels –