1. 程式人生 > >Apache Camel FTP + Spring Boot 配置簡述

Apache Camel FTP + Spring Boot 配置簡述

說明

由於之前專案中已經使用 apache camel ftp 工具來處理 ftp 相關操作,這裡沿用該工具。簡要配置如下:

工具包

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-spring-boot-starter</artifactId>
    <version>2.19.4</version>
</dependency>

<dependency>
    <groupId
>
org.apache.camel</groupId> <artifactId>camel-ftp</artifactId> <version>2.19.4</version> </dependency>

配置檔案示例

說明:

  • localWorkDirectory : 本地工作目錄,由於本專案使用的 ftp 介面檔案較大,為了防止其直接載入到記憶體導致記憶體溢位,配置本地工作目錄來快取下載中的檔案。
  • useUserKnownHostsFile : 是否使用主機本地的known_hosts,配置為false,則會預設到classpath下查詢。
  • filter : 過濾方法。
ftp.server.uri=sftp://${ftp.url}\
               ?username=${ftp.username}\
               &password=${ftp.password}\
               &useUserKnownHostsFile=false\
               &localWorkDirectory=${ftp.local.work.directory}\
               &delay=1h\
               &readLock=rename
\ &filter=#ftpDownloadFileFilter\ &stepwise=false # 使用者名稱密碼 ftp.url=192.168.192.128:22022 ftp.username=ftp_test ftp.password=ftp_test_pw # 本地工作目錄 ftp.local.work.directory=D:/TestData/sunknew/sftp/temp # 本地同步目錄 ftp.local.data.dir=D:/TestData/sunknew/sftp/data

known_hosts示例

[192.168.192.128]:22022 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIpYfg3lLmpP/NKEi5aF9ReY42JOBYf40gkdcIZe7hi+KXgvYOwSjSnZ1O71gaeJvTPk8UU01j8tgQegCNwSNqo=
[192.168.192.128]:22022 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAxf7XvwmHHjtI3wJwURMd4hV+pP6md7+g+FouZNWecHarhen+bS795EFGvYa4c/srKRg4/Kj70gF0wV62gDkXGgrNMR5mFr8NGR0fFoA5E0K2k7bZNvm2+/ngU6Sno/olbb3IlfQ2c2YmnFqaDPIINOnyZC4UyJA3Wjm1xGf7zrUn3PQMpS4+QmvhpNj2JDzQfR8cb429Cjmw0JUrtJRrfPNlQUaqeXVl6RmyZw+Np/yXf/4KSYs4SN1P9+0LF00Qewm6ch70N8vnY3DyRRDx24oQohU72gjkJsA8bEkLxZHEzg52qpaZaN/+sl2NrmebarCXl+/eOkSqqm+Ejcv5rw==

Filter示例

package com.sunknew.ftp.filter;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.camel.component.file.GenericFile;
import org.apache.camel.component.file.GenericFileFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class FtpDownloadFileFilter implements GenericFileFilter<Object> {

    private static Logger logger = LoggerFactory.getLogger(FtpDownloadFileFilter.class);

    @Value("${ftp.local.data.dir}")
    private String localDir;

    /**
     * 過濾下載檔案
     * @author sunk
     */
    @Override
    public boolean accept(GenericFile<Object> file) {

        try {
            String fileName = file.getFileName();
            long lastModified = file.getLastModified();

            return isLatestFile(lastModified, 3) && !isInLocalDir(fileName) ? true : false;
        } catch (Exception e) {
            logger.error("ftp download file filter error !", e);
            return false;
        }
    }

    /**
     * 檔案是否為最近幾天內的
     * <p> 用於過濾一部分歷史資料
     * @author sunk
     */
    private boolean isLatestFile(long lastModified, int dateNum) {

        Calendar calLastMod = Calendar.getInstance();
        calLastMod.setTimeInMillis(lastModified);

        Calendar calThreshold = Calendar.getInstance();
        calThreshold.add(Calendar.DATE, - dateNum);

        return calLastMod.compareTo(calThreshold) > 0 ? true : false;
    }

    /**
     * 檔案是否已在本地目錄中
     * @author sunk
     */
    private boolean isInLocalDir(String fileName) {
        try {
            //獲取本地資料夾中已下載的檔名
            List<String> localFileNames = Files.walk(Paths.get(localDir))
                    .filter(Files::isRegularFile)
                    .map(Path::getFileName)
                    .map(Path::toString)
                    .collect(Collectors.toList());
            //logger.info("local downloaded files : " + Arrays.toString(localFileNames.toArray()));

            return localFileNames.contains(fileName) ? true : false;
        } catch (Exception e) {
            logger.error("get local downloaded files fail !", e);
            return true;
        }
    }
}

Route示例

由於本專案中檔案較大,不在此處配置處理方法

package com.sunknew.ftp.task;

import java.net.InetAddress;

import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class FtpDownloadRoute extends RouteBuilder {

    private static Logger logger = LoggerFactory.getLogger(FtpDownloadRoute.class);

    @Value("${ftp.server.uri}")
    private String ftpUri;

    @Value("${ftp.local.data.dir}")
    private String localDir;

    @Value("${host.nodes}")
    private String hostNodes;

    @Value("${ftp.task.start}")
    private boolean isStart;

    @Override
    public void configure() throws Exception {

        if (isStart && isExecHost()) {
            from(ftpUri).to("file:" + localDir)
                .log(LoggingLevel.INFO, logger, "download file ${file:name} complete.");
        }
    }

    /**
     * 判斷是否為執行任務的主機
     * @author sunk
     */
    private boolean isExecHost() {
        String hostName = "";
        try {
            hostName = InetAddress.getLocalHost().getHostName();
        } catch (Exception e) {
            logger.error("get hostname fail !", e);
            return false;
        }
        return hostName.endsWith(hostNodes.split(",")[0]);
    }
}

參考

1.Apache Camel: FTP2
2.Apache Camel: File2
3.Apache Camel: Spring Boot
4.Apache Camel 與 Spring Boot 整合,通過FTP定時採集、處理檔案