今天写了一个FTPPool,贴上来分享一下。
使用了相关的开源工具包2个:commons-net-3.0.1.jar和commons-pool-1.6.jar。
代码如下:
Pool.java:使用GenericObjectPool作为连接池管理连接,简单封装了borrowObject,returnObject。
public abstract class Pool<T> { private final GenericObjectPool<T> internalPool; public Pool(GenericObjectPool.Config poolConfig, PoolableObjectFactory factory) { this.internalPool = new GenericObjectPool<T>(factory, poolConfig); } public T getResource(){ try{ return this.internalPool.borrowObject(); }catch(Exception e){ e.printStackTrace(); return null; } } public void returnResource(T resource){ try { this.internalPool.returnObject(resource); }catch (Exception e) { e.printStackTrace(); } } public void destroy(){ try{ this.internalPool.close(); }catch (Exception e) { e.printStackTrace(); } } public int inPoolSize(){ try{ return this.internalPool.getNumIdle(); }catch(Exception e){ e.printStackTrace(); return 0; } } public int borrowSize(){ try{ return this.internalPool.getNumActive(); }catch(Exception e){ e.printStackTrace(); return 0; } } }
FTPPool.java:继承了抽象类Pool,在构造方法中实例化FTPPoolableObjectFactory,以处理GenericObjectPool中的操作。
public class FTPPool extends Pool<FTPClient>{ public FTPPool(Config poolConfig,String host,int port,String user,String password,String passiveModeConf){ super(poolConfig, new FTPPoolableObjectFactory(host, port, user, password, passiveModeConf)); } }
FTPPoolableObjectFactory.java:继承BasePoolableObjectFactory,其中的方法分别为:
GenericObjectPool内部会回调makeObject创建对象。
GenericObjectPool内部会回调destroyObject销毁对象。
GenericObjectPool内部会回调validateObject检验对象。
public class FTPPoolableObjectFactory extends BasePoolableObjectFactory{ private String host; private int port; private String user; private String password; private String passiveModeConf; public FTPPoolableObjectFactory(String host,int port,String user,String password,String passiveModeConf){ this.host = host; System.out.println("host:"+host); this.port = port; System.out.println("port:"+port); this.user = user; System.out.println("user:"+user); this.password = password; System.out.println("password:"+password); this.passiveModeConf = passiveModeConf; System.out.println("passiveModeConf:"+passiveModeConf); } @Override public Object makeObject() throws Exception { FTPClient ftpClient = new FTPClient(); ftpClient.connect(host, port); ftpClient.setControlKeepAliveTimeout(300);//set timeout to 5 minutes ftpClient.login(user, password); boolean passiveMode = false; if (passiveModeConf == null || Boolean.parseBoolean(passiveModeConf) == true){ passiveMode = true; } if (passiveMode) { ftpClient.enterLocalPassiveMode(); } ftpClient.setFileType(FTP.BINARY_FILE_TYPE); return ftpClient; } @Override public void destroyObject(Object obj) throws Exception { if(obj instanceof FTPClient){ FTPClient ftpClient=(FTPClient)obj; if(!ftpClient.isConnected()) return ; try{ ftpClient.disconnect(); }catch(Exception e){ e.printStackTrace(); } } } @Override public boolean validateObject(Object obj) { if(obj instanceof FTPClient){ FTPClient ftpClient=(FTPClient)obj; try{ return ftpClient.isConnected(); }catch(Exception e){ return false; } } return false; } }
最后是使用方法:
public static void main(String[] args) throws Exception{ GenericObjectPool.Config config = new Config(); //最大池容量 config.maxActive=5; //从池中取对象达到最大时,继续创建新对象. config.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; //池为空时取对象等待的最大毫秒数. config.maxWait=60*1000; //取出对象时验证(此处设置成验证ftp是否处于连接状态). config.testOnBorrow=true; //还回对象时验证(此处设置成验证ftp是否处于连接状态). config.testOnReturn=true; FTPPool pool = new FTPPool(config,"XXXXXX",21,"xxxxxx","xxxxxx","true"); System.out.println("borrowSize1:"+pool.borrowSize()); System.out.println("inPoolSize1:"+pool.inPoolSize()); long begin=System.currentTimeMillis(); for(int i=0;i<8;i++){ FTPClient ftpClient = pool.getResource(); System.out.println("ftpClient"+(i+1)+" isConnected:"+ftpClient.isConnected()); //ftpClient.disconnect(); //pool.returnResource(ftpClient); pool.returnResource(ftpClient); } System.out.println("time:"+(System.currentTimeMillis()-begin)); System.out.println("borrowSize2:"+pool.borrowSize()); System.out.println("inPoolSize2:"+pool.inPoolSize()); pool.destroy(); }
其中testOnBorrow、testOnReturn设置为true时,会在回调中调用validateObject方法进行对象检验。 pool.getResource()方法会从池中取出对象,pool.returnResource()方法会向池中还回对象。具体API含义请参见commons-pool的文档。
以上就是一个简单的FTPPool的实现,commons-pool除了GenericObjectPool外还提供了不同的池。感觉有了这个开源工具随便写个连接池都方便很多了,所以一定要好好研究下。另外希望本文对看到的人有所帮助。
(PS:这段代码其实是参考了开源工具jedis-pool的源代码而写成,看来看开源代码对编程能力有很大提升。另外,今天要happy birthday!)