java ftpClient 连接池设计

1、FtpManager 类中,需要创建连接池管理的Map

private static ConcurrentHashMap<String, FtpClientPool> pools = new ConcurrentHashMap<String, FtpClientPool>();

2、定义具体的操作方法,如删除

public static void deleteFiles(List<FtpEntity> ftpEntitys, String filePath, Set<String> fileNames) throws Exception {

        if (null == fileNames || fileNames.size() <= 0) {

            return;

        }

        Exception e = null;

        for (FtpEntity ftpEntity : ftpEntitys) {

            FTPClient ftpClient = null;

            try {

                ftpClient = borrowClient(ftpEntity);

                makeDirectory(ftpClient, ftpEntity.getTemp(), filePath);

                for (String fileName : fileNames) {

                    try {

                        ftpClient.deleteFile(fileName);

                    } catch (Exception e1) {

                        LOGGER.log(Level.SEVERE, "delete " + fileName + " error", e1);

                    }

                }

            } catch (Exception ex) {

                LOGGER.log(Level.SEVERE, "uploadFile error", ex);

                returnBrokenClient(ftpClient);

                ftpClient = null;

                e = ex;

            } finally {

                if (ftpClient != null) {

                    returnClient(ftpClient);

                }

            }

        }

        if (null != e) {

            throw e;

        }

    }

3、borrowClient 是哪里来的呢??

    public static FTPClient borrowClient(FtpEntity ftpEntity) {

        String url = ftpEntity.getUrl();

        if (!url.endsWith(SPLITTER)) {

            url = url + SPLITTER;

        }

        String hostName = url.substring(FTP_FIX, url.indexOf(SPLITTER, FTP_FIX));

        String username = ftpEntity.getUsername();

        String password = ftpEntity.getPassword();

        String poolId = constructPoolId(hostName, username, password);

        FtpClientPool pool = pools.get(poolId);

        if (pool == null) {

            final FtpClientPool value = new FtpClientPool(hostName, username, password);

            pool = pools.putIfAbsent(poolId, value);

            if (pool == null) {

                pool = value;

            }

        }

        return pool.borrowClient();

    }

4、FtpClientPool 哪里来的呢? 它是ftpManager 的一个内部类

private static class FtpClientPool {

        private final GenericObjectPool<FTPClient> internalPool;

        private FtpClientPool(String hostname, String username, String password) {

            this.internalPool = new GenericObjectPool<FTPClient>(new FtpClientFactory(hostname, username, password));

            // this is important,change to root dir when borrow from pool,ref validateObject method.

            this.internalPool.setTestOnBorrow(true);

            this.internalPool.setMaxTotal(50);

            this.internalPool.setMaxIdle(16);

            // this.internalPool.setMinEvictableIdleTimeMillis(60000);

            // this.internalPool.setTimeBetweenEvictionRunsMillis(60000);

            // this.internalPool.setTestWhileIdle(true);

            this.internalPool.setBlockWhenExhausted(true);

            // this.internalPool.setNumTestsPerEvictionRun(10);

            // this.internalPool.setMaxTotal(Integer.MAX_VALUE);

            this.internalPool.setMaxWaitMillis(MaxWaitMillis);

            // this.internalPool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);

        }

        /**

         * 功能描述: <br>

         * 获取链接 〈功能详细描述〉

         * 

         * @return

         * @see [相关类/方法](可选)

         * @since [产品/模块版本](可选)

         */

        public FTPClient borrowClient() {

            try {

                return this.internalPool.borrowObject();

            } catch (Exception e) {

                throw new RuntimeException("Could not borrowClient from pool", e);

            }

        }

        /**

         * 功能描述: <br>

         * 初始化连接 〈功能详细描述〉

         * 

         * @param client

         * @see [相关类/方法](可选)

         * @since [产品/模块版本](可选)

         */

        public void returnClient(FTPClient client) {

            try {

                this.internalPool.returnObject(client);

            } catch (Exception e) {

//                LOGGER.log(Level.WARNING, "Could not returnClient from pool", e);

            }

        }

        public void returnBrokenClient(FTPClient client) {

            try {

                this.internalPool.invalidateObject(client);

            } catch (Exception e) {

//                LOGGER.log(Level.WARNING, "Could not returnBrokenClient from pool", e);

            }

        }

        /**

         * 功能描述: <br>

         * 销毁链接 〈功能详细描述〉

         * 

         * @see [相关类/方法](可选)

         * @since [产品/模块版本](可选)

         */

        public void destroy() {

            try {

                this.internalPool.close();

            } catch (Exception e) {

//                LOGGER.log(Level.WARNING, "Could not destroy pool", e);

            }

        }

    }

5、FtpClientFactory 哪里来的呢?它也是一个内部类

private static class FtpClientFactory implements PooledObjectFactory<FTPClient> {

        private String hostname;

        private String username;

        private String password;

        private FtpClientFactory(String hostname, String username, String password) {

            this.hostname = hostname;

            this.username = username;

            this.password = password;

        }

        /*

         * (non-Javadoc)

         * @see org.apache.commons.pool.BasePoolableObjectFactory#makeObject()

         */

        public FtpClientWrapper create() throws Exception {

            FtpClientWrapper ftpClient = null;

            Boolean flag = false;

            Exception e = null;

            for (int i = 0; i < RECONNECT_TIMES; i++) {

                try {

                    ftpClient = new FtpClientWrapper(this.hostname, this.username, this.password);

                    ftpClient.setConnectTimeout(CONNECT_TIMEOUT);

                    // ftpClient.setDefaultTimeout(CONNECT_TIMEOUT);

                    ftpClient.setControlEncoding("utf-8");

                    ftpClient.connect(hostname);

                    ftpClient.setDataTimeout(DATA_TIMEOUT);

                    int reply = ftpClient.getReplyCode();

                    if (!FTPReply.isPositiveCompletion(reply)) {

                        ftpClient.disconnect();

                        throw new Exception("FTP Connect fail");

                    }

                    if (!ftpClient.login(username, password)) {

                        ftpClient.disconnect();

                        throw new Exception("Invalid username and password");

                    }

                    ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);

                    ftpClient.setBufferSize(BUFFER_SIZE);

                    ftpClient.enterLocalPassiveMode();

                    ftpClient.setRootDir(ftpClient.printWorkingDirectory());

                    flag = true;

                    break;

                } catch (Exception ex) {

//                    LOGGER.log(Level.WARNING, "test....Can not create ftpClient," + this.hostname, ex);

                    try {

                        destroyObject(ftpClient);

                    } catch (Exception e1) {

//                        LOGGER.log(Level.WARNING, "test...Can not close ftpClient," + this.hostname, e1);

                    }

                    e = ex;

                    Thread.sleep(RECONNECT_SLEEP_TIME);

                }

            }

            if (!flag) {

//                LOGGER.log(Level.WARNING, "test....Can not create ftpClient in three times," + this.hostname);

                try {

                    destroyObject(ftpClient);

                } catch (Exception e1) {

//                    LOGGER.log(Level.WARNING, "Can not close ftpClient", e1);

                }

                throw new Exception(hostname + " cat not connect.", e);

            }

            return ftpClient;

        }

        public void destroyObject(FTPClient ftpClient) throws Exception {

            closeFtpClient(ftpClient);

        }

        @Override

        public PooledObject<FTPClient> makeObject() throws Exception {

            // TODO Auto-generated method stub

            return new DefaultPooledObject<FTPClient>(create());

        }

        @Override

        public void destroyObject(PooledObject<FTPClient> p) throws Exception {

            closeFtpClient(p.getObject());

        }

        @Override

        public boolean validateObject(PooledObject<FTPClient> p) {

            try {

                ((FtpClientWrapper) p.getObject()).changeToRootDir();

                return true;

            } catch (Exception e) {

//                LOGGER.log(Level.WARNING, "failed to changeToRootDir,validate failed.");

                throw new RuntimeException("Failed to validate client: " + e, e);

            }

        }

        @Override

        public void activateObject(PooledObject<FTPClient> p) throws Exception {

            // TODO Auto-generated method stub

        }

        @Override

        public void passivateObject(PooledObject<FTPClient> p) throws Exception {

            // TODO Auto-generated method stub

        }

    }

6、FtpClientWrapper 哪里来的呢,没错,还是内部类

public static class FtpClientWrapper extends FTPClient {

        private String poolId;

        private String rootDir;

        public FtpClientWrapper(String ip, String username, String password) {

            super();

            this.poolId = constructPoolId(ip, username, password);

        }

        /**

         * 功能描述: <br>

         * get set方法 〈功能详细描述〉

         * 

         * @return : id

         * @see [相关类/方法](可选)

         * @since [产品/模块版本](可选)

         */

        public String getPoolId() {

            return poolId;

        }

        /**

         * 功能描述: <br>

         * get set方法 〈功能详细描述〉

         * 

         * @see [相关类/方法](可选)

         * @since [产品/模块版本](可选)

         */

        public void setRootDir(String rootDir) {

            this.rootDir = rootDir;

        }

        /**

         * 功能描述: <br>

         * 返回根目录 〈功能详细描述〉

         * 

         * @throws Exception

         * @see [相关类/方法](可选)

         * @since [产品/模块版本](可选)

         */

        public void changeToRootDir() throws Exception {

            changeWorkingDirectory(rootDir);

        }

    }

猜你喜欢

转载自bai2mumu.iteye.com/blog/2231916