如何轮询目录中的文件?

时间:2014-07-10 14:31:14

标签: spring spring-batch spring-integration

我需要能够使用SCP轮询目录中的特定文件,一旦文件处理完毕,就需要继续进行轮询。

Spring Batch可以实现吗?

2 个答案:

答案 0 :(得分:2)

处理此问题的常用方法是使用Spring Integration。我解决这个问题的方法是使用Spring Integration流程,该流程使用SFTP入站通道适配器来检索文件,然后将传输的名称传递给Spring Batch以启动。该流程实际上类似于我在Spring Batch网络研讨会中的SpringBatchIntegration中的示例:https://github.com/mminella/SpringBatchWebinar

在那个例子中,我使用Twitter来启动这项工作。您唯一需要改变的是SFTP的推特。

答案 1 :(得分:1)

我必须解决相同的问题(但只是访问本地文件系统)并且我没有在框架中找到任何解决方案,所以我最终创建了自己的类来轮询文件并创建资源。我知道这只是一种解决方法,但到目前为止我还没有找到更好的方法。

我不记得在哪里(可能在"重试处理"部分)但我在文档中读到类似"批处理作业不应该尝试解决像文件未找到,连接断开等等,这些错误应该会导致作业引发错误,由操作员处理" 所以我放弃了......

另一方面,Spring Retry是Spring批处理的一部分,现在是一个新的独立库,也许你可以假设文件在那里,如果读者没有找到它,让步骤失败并建立一个&#34 ;重试政策"对于那一步,但对我而言是过度的。

这就是我所做的:

<bean id="resourceFactory"
      class="com.mycompany.batch.zip.ResourceFactory">
    <property name="retryAttemps" value="${attemps}" />
    <property name="timeBetweenAttemps" value="${timeBetweenAttemps}"/>
</bean>

<bean id="myResource"
      factory-bean="resourceFactory" factory-method="create" scope="step">
    <constructor-arg value="${absolutepath}" type="java.lang.String"  />
</bean>

<!--step scope to avoid looking for the file when deployment-->
<bean id="myReader"
      class="org.springframework.batch.item.xml.StaxEventItemReader" scope="step">
    <property name="fragmentRootElementName" value="retailer" />
    <property name="unmarshaller" ref="reportUnmarshaller" />
    <property name="resource" ref="myResource" />
</bean>

这是我的班级:

public class ResourceFactory {

    public static final Logger LOG= LoggerFactory.getLogger(ResourceFactory.class);
    private int retryAttemps;
    private long timeBetweenAttemps;

    public Resource create(String resource) throws IOException, InterruptedException {
        Resource r;
        File f=new File(resource);
        int attemps=1;
        while (!f.exists()) {
            if (attemps<this.retryAttemps) {
                attemps++;
                LOG.warn("File "+resource+" not found, waiting "+timeBetweenAttemps+
                           " before retrying. Attemp: "+attemps+" of "+this.retryAttemps);
                Thread.sleep(this.timeBetweenAttemps);
            } else {
                throw new FileNotFoundException(resource);
            }
            if (resource!=null && resource.endsWith(".zip")) {
                ZipFile zipFile = new ZipFile(resource);
                ZipEntry entry=zipFile.entries().nextElement();
                if (entry==null) {
                    throw new FileNotFoundException("The zip file has no entries inside");
                }

                //TODO Test if a buffered Stream is faster than the raw InputStream
                InputStream is=new BufferedInputStream(zipFile.getInputStream(entry));

                r= new InputStreamResource(is);
                if (LOG.isInfoEnabled()) {
                    int size=(int)entry.getSize();
                    LOG.info("Opening a compressed file of "+size+" bytes");
                }
            } else {
                LOG.info("Opening a regular file");
                r= new FileSystemResource(f);
            }
        }
        return r;
    }
}

如果有人知道更好的方法,我很乐意删除这个答案(并实施新的解决方案)

PS:顺便说一下,我在查看这篇文章时发现我的代码中有一些错误,所以对我而言,即使没有其他答案也是如此:)