FTPClient 线程池实现与端口说明

547 阅读3分钟
21/tcp FTP 文件传输协议 
22/tcp SSH 安全登录、文件传送(SCP)和端口重定向 
23/tcp Telnet 不安全的文本传送 
25/tcp SMTP Simple Mail Transfer Protocol (E-mail) 
69/udp TFTP Trivial File Transfer Protocol 
79/tcp finger Finger 
80/tcp HTTP 超文本传送协议 (WWW) 
88/tcp Kerberos Authenticating agent 
110/tcp POP3 Post Office Protocol (E-mail) 
113/tcp ident old identification server system 
119/tcp NNTP used for usenet newsgroups 
220/tcp IMAP3 
443/tcp HTTPS used for securely transferring web pages

pom添加依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
    <groupId>commons-pool</groupId>
    <artifactId>commons-pool</artifactId>
    <version>1.6</version>
</dependency>
public class FTPTemplate {

    public static FTPClientPool ftpClientPool;

    public static FTPClient ftpClient;  ##查看客户端

    public static FTPClient writeftpClient;  ## 上传客户端


    public FTPTemplate(FTPProperties ftpProperties) {
        FTPClientFactory factory = new FTPClientFactory(ftpProperties);
        try {
            ftpClientPool = new FTPClientPool(factory);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接对象
     *
     * @return
     * @throws Exception
     */
    public static FTPClient getFTPClient() throws Exception {        //初始化的时候从队列中取出一个连接
        if (ftpClient == null) {
            synchronized (ftpClientPool) {
                ftpClient = ftpClientPool.borrowObject();
            }
        }
        return ftpClient;
    }

    /**
     * 获取连接对象
     *
     * @return
     * @throws Exception
     */
    public static FTPClient getWriteFTPClient() throws Exception {        //初始化的时候从队列中取出一个连接
        if (writeftpClient == null) {
            synchronized (ftpClientPool) {
                writeftpClient = ftpClientPool.borrowObject();
            }
        }
        return writeftpClient;
    }

    /**
     * 当前命令执行完成命令完成
     *
     * @throws IOException
     */
    public void complete() throws IOException {
        ftpClient.completePendingCommand();
    }

    /**
     * 当前线程任务处理完成,加入到队列的最后
     *
     * @return
     */
    public void disconnect() throws Exception {
        ftpClientPool.addObject(ftpClient);
    }

    /**
     * Description: 向FTP服务器上传文件
     *
     * @param remoteFile 上传到FTP服务器上的文件名
     * @param input      本地文件流
     * @return 成功返回true,否则返回false
     * @Version1.0
     */
    public static boolean uploadFile(String remoteFile, InputStream input) {
        boolean result = false;
        try {
            getWriteFTPClient();
            writeftpClient.enterLocalPassiveMode();
            result = writeftpClient.storeFile(remoteFile, input);
            input.close();
            writeftpClient.disconnect();
            writeftpClient = null;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * Description: 向FTP服务器上传文件
     *
     * @param remoteFile 上传到FTP服务器上的文件名
     * @param localFile  本地文件
     * @return 成功返回true,否则返回false
     * @Version1.0
     */
    public static boolean uploadFile(String remoteFile, String localFile) {
        FileInputStream input = null;
        try {
            input = new FileInputStream(new File(localFile));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return uploadFile(remoteFile, input);
    }

    /**
     * 拷贝文件
     *
     * @param fromFile
     * @param toFile
     * @return
     * @throws Exception
     */
    public boolean copyFile(String fromFile, String toFile) throws Exception {
        InputStream in = getFileInputStream(fromFile);
        getFTPClient();
        boolean flag = ftpClient.storeFile(toFile, in);
        in.close();
        return flag;
    }

    /**
     * 获取文件输入流
     *
     * @param fileName
     * @return
     * @throws IOException
     */
    public static InputStream getFileInputStream(String fileName) throws Exception {
        ByteArrayOutputStream fos = new ByteArrayOutputStream();
        getFTPClient();
        ftpClient.retrieveFile(fileName, fos);
        ByteArrayInputStream in = new ByteArrayInputStream(fos.toByteArray());
        fos.close();
        return in;
    }

    /**
     * Description: 从FTP服务器下载文件
     *
     * @return
     * @Version1.0
     */
    public static boolean downFile(String remoteFile, String localFile) {
        boolean result = false;
        try {
            getFTPClient();
            OutputStream os = new FileOutputStream(localFile);
            ftpClient.retrieveFile(remoteFile, os);
            ftpClient.logout();
            ftpClient.disconnect();
            ftpClient = null;
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 从ftp中获取文件流
     *
     * @param filePath
     * @return
     * @throws Exception
     */
    public static InputStream getInputStream(String filePath) throws Exception {
        getFTPClient();
        InputStream inputStream = ftpClient.retrieveFileStream(filePath);
        return inputStream;
    }

    /**
     * ftp中文件重命名
     *
     * @param fromFile
     * @param toFile
     * @return
     * @throws Exception
     */
    public boolean rename(String fromFile, String toFile) throws Exception {
        getFTPClient();
        boolean result = ftpClient.rename(fromFile, toFile);
        return result;
    }

    /**
     * 获取ftp目录下的所有文件
     *
     * @param dir
     * @return
     */
    public FTPFile[] getFiles(String dir) throws Exception {
        getFTPClient();
        FTPFile[] files = new FTPFile[0];
        try {
            files = ftpClient.listFiles(dir);
        } catch (Throwable thr) {
            thr.printStackTrace();
        }
        return files;
    }

    /**
     * 获取ftp目录下的某种类型的文件
     *
     * @param dir
     * @param filter
     * @return
     */
    public FTPFile[] getFiles(String dir, FTPFileFilter filter) throws Exception {
        getFTPClient();
        FTPFile[] files = new FTPFile[0];
        try {
            files = ftpClient.listFiles(dir, filter);
        } catch (Throwable thr) {
            thr.printStackTrace();
        }
        return files;
    }

    /**
     * 创建文件夹
     *
     * @param remoteDir
     * @return 如果已经有这个文件夹返回false
     */
    public boolean makeDirectory(String remoteDir) throws Exception {
        getFTPClient();
        boolean result = false;
        try {
            result = ftpClient.makeDirectory(remoteDir);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public boolean mkdirs(String dir) throws Exception {
        boolean result = false;
        if (null == dir) {
            return result;
        }
        getFTPClient();
        ftpClient.changeWorkingDirectory("/");
        StringTokenizer dirs = new StringTokenizer(dir, "/");
        String temp = null;
        while (dirs.hasMoreElements()) {
            temp = dirs.nextElement().toString();            //创建目录
            ftpClient.makeDirectory(temp);            //进入目录
            ftpClient.changeWorkingDirectory(temp);
            result = true;
        }
        ftpClient.changeWorkingDirectory("/");
        return result;
    }
}

public class FTPClientPool implements ObjectPool<FTPClient> {
    private static final int DEFAULT_POOL_SIZE = 10;
    public BlockingQueue<FTPClient> blockingQueue;
    private FTPClientFactory factory;

    public FTPClientPool(FTPClientFactory factory) throws Exception {
        this(DEFAULT_POOL_SIZE, factory);
    }

    public FTPClientPool(int poolSize, FTPClientFactory factory) throws Exception {
        this.factory = factory;
        this.blockingQueue = new ArrayBlockingQueue<FTPClient>(poolSize);
        initPool(poolSize);
    }

    /**
     * 初始化连接池
     *
     * @param maxPoolSize 最大连接数
     * @throws Exception
     */
    private void initPool(int maxPoolSize) throws Exception {
        int count = 0;
        while (count < maxPoolSize) {
            this.addObject();
            count++;
        }
    }

    /**
     * 从连接池中获取对象
     */
    @Override
    public FTPClient borrowObject() throws Exception {
        FTPClient client = blockingQueue.take();
        if (client == null) {
            client = factory.makeObject();
        } else if (!factory.validateObject(client)) {
            invalidateObject(client);
            client = factory.makeObject();
        }
        return client;
    }

    /**
     * 返还一个对象(链接)
     */
    @Override
    public void returnObject(FTPClient client) throws Exception {
        if ((client != null) && !blockingQueue.offer(client, 2, TimeUnit.MINUTES)) {
            try {
                factory.destroyObject(client);
            } catch (Exception e) {
                throw e;
            }
        }
    }

    /**
     * 移除无效的对象(FTP客户端)
     */
    @Override
    public void invalidateObject(FTPClient client) throws Exception {
        blockingQueue.remove(client);
    }

    /**
     * 增加一个新的链接,超时失效
     */
    @Override
    public void addObject() throws Exception {
        blockingQueue.offer(factory.makeObject(), 2, TimeUnit.MINUTES);
    }

    /**
     * 重新连接
     */
    public FTPClient reconnect() throws Exception {
        return factory.makeObject();
    }

    /**
     * 获取空闲链接数(这里暂不实现)
     */
    @Override
    public int getNumIdle() {
        return blockingQueue.size();
    }

    /**
     * 获取正在被使用的链接数
     */
    @Override
    public int getNumActive() {
        return DEFAULT_POOL_SIZE - getNumIdle();
    }

    @Override
    public void clear() throws Exception {

    }

    /**
     * 关闭连接池
     */
    @Override
    public void close() {
        try {
            while (blockingQueue.iterator().hasNext()) {
                FTPClient client = blockingQueue.take();
                factory.destroyObject(client);
            }
        } catch (Exception e) {
            log.error("close ftp client pool failed...{}", e);
        }
    }

    /**
     * 增加一个新的链接,超时失效
     */
    public void addObject(FTPClient ftpClient) throws Exception {
        blockingQueue.put(ftpClient);
    }
}
public class FTPClientFactory implements PoolableObjectFactory<FTPClient> {

    private FTPProperties ftpProperties;

    public FTPClientFactory(FTPProperties ftpProperties) {
        this.ftpProperties = ftpProperties;
    }

    @Override
    public FTPClient makeObject() throws Exception {
        FTPClient ftpClient = new FTPClient();
        ftpClient.setControlEncoding(ftpProperties.getEncoding());
        ftpClient.setConnectTimeout(ftpProperties.getClientTimeout());
        try {
            ftpClient.connect(ftpProperties.getHost(), ftpProperties.getPort());
            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                log.warn("FTPServer refused connection");
                return null;
            }
            boolean result = ftpClient.login(ftpProperties.getUsername(), ftpProperties.getPassword());
            ftpClient.setFileType(ftpProperties.getTransferFileType());
            if (!result) {
                log.warn("ftpClient login failed... username is {}", ftpProperties.getUsername());
            }
        } catch (Exception e) {
            log.error("create ftp connection failed...{}", e);
            throw e;
        }
        return ftpClient;
    }

    @Override
    public void destroyObject(FTPClient ftpClient) throws Exception {
        try {
            if (ftpClient != null && ftpClient.isConnected()) {
                ftpClient.logout();
            }
        } catch (Exception e) {
            log.error("ftp client logout failed...{}", e);
            throw e;
        } finally {
            if (ftpClient != null) {
                ftpClient.disconnect();
            }
        }

    }

    @Override
    public boolean validateObject(FTPClient ftpClient) {
        try {
            return ftpClient.sendNoOp();
        } catch (Exception e) {
            log.error("Failed to validate client: {}");
        }
        return false;
    }

    @Override
    public void activateObject(FTPClient obj) throws Exception {        //Do nothing

    }

    @Override
    public void passivateObject(FTPClient obj) throws Exception {        //Do nothing

    }
}

注意:FtpClient可以实现同时上传和下载,只要FTPClient 不是同一个对象就可以