一、描述:
apache commons-pool本质上是"对象池",即通过一定的规则来维护对象集合的容器;commons-pool用来实现"连接池"或"任务池"等,dbcp也是基于commons-pool实现。
二、commons-pool实现思路:
将"对象集合"池化,任何通过pool进行对象存取的操作,都会严格按照"pool配置"试试的创建对象、阻塞控制、销毁对象等。实现了对象集合的管理以及对象的分发。
a.将创建对象的方式,使用工厂模式;
b.通过"pool配置"来约束对象存取的时机
c.将对象列表保存在队列中(LinkedList)
三、实例演示(FTP连接池管理):
public abstract class AbstractObjectPool<T>{ private final GenericObjectPool<T> internalPool; public AbstractObjectPool(GenericObjectPool.Config poolConfig, PoolableObjectFactory factory){ this.internalPool=new GenericObjectPool(factory,poolConfig); } public T getResource(){ return this.internalPool.borrowObject(); } public void returnResource(T resource){ this.internalPool.returnObject(resource); } public void destroy(){ this.internalPool.close(); } }
FTPPool.java继承了抽象类AbstractObjectPool.java,在构造方法中实例化FTPPoolableObjectFactory,处理GenericObjectPool中的操作。
public class FTPPool extends<AbstractObjectPool>{ public FTPPool(GenericObjectPool.Config poolConfig,String host,int port,String user,String password,String passiveModeConf){ super(poolConfig,new FTPPoolableObjectFactort(host, port, user, password, passiveModeConf)); } }
FTPPoolableObjectFactort.java继承BasePoolableObjectFactory,其中的方法分别为:
GenericObjectPool内部会回调makeObject创建对象
GenericObjectPool内部会回调destroyObject销毁对象
GenericObjectPool内部会回调validateObject检验对象
public class FTPPoolableObjectFactory extends BasePoolableObjectFactory<FTPClient>{ 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; this.port = port; this.user = user; this.password = password; this.passiveModeConf = passiveModeConf; } @Override public FTPClient makeObject() throws Exception { FTPClient ftpClient = getFTPClient(); return ftpClient; } @Override public void destroyObject(FTPClient client) throws Exception { if (client != null) { disconnect(client); } } @Override public boolean validateObject(FTPClient obj) { if (obj != null) { FTPClient ftpClient = obj; try { return ftpClient.isConnected(); } catch (Exception e) { LOGGER.error(e.getMessage(), e); return false; } } return false; } private void setFileType(FTPClient ftpClient) throws FTPClientException { try { if (binaryTransfer) { ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); } else { ftpClient.setFileType(FTPClient.ASCII_FILE_TYPE); } } catch (IOException e) { throw new FTPClientException("Could not to set file type.", e); } msg = " setFileType(FTPClient " + ftpClient + ") 结束"; LOGGER.error(msg); } private FTPClient getFTPClient() throws FTPClientException { FTPClient ftpClient = new FTPClient(); // 构造一个FtpClient实例 ftpClient.setControlEncoding(encoding); // 设置字符集 connect(ftpClient); // 连接到ftp服务器 // 设置为passive模式 if (passiveMode) { ftpClient.enterLocalPassiveMode(); } setFileType(ftpClient); // 设置文件传输类型 try { ftpClient.setSoTimeout(CLIENT_TIMEOUT); } catch (SocketException e) { throw new FTPClientException("Set timeout error.", e); } return ftpClient; } private boolean connect(FTPClient ftpClient) throws FTPClientException { try { ftpClient.connect(host, port); // 连接后检测返回码来校验连接是否成功 int reply = ftpClient.getReplyCode(); if (FTPReply.isPositiveCompletion(reply)) { // 登陆到ftp服务器 msg = "login(" + username + ", " + password + ")"; if (ftpClient.login(username, password)) { setFileType(ftpClient); return true; } } else { ftpClient.disconnect(); throw new FTPClientException("FTP server refused connection."); } } catch (IOException e) { if (ftpClient.isConnected()) { try { ftpClient.disconnect(); // 断开连接 } catch (IOException e1) { throw new FTPClientException("Could not disconnect from server.", e); } } throw new FTPClientException("Could not connect to server.", e); } return false; } private void disconnect(FTPClient ftpClient) throws FTPClientException { try { ftpClient.logout(); if (ftpClient.isConnected()) { ftpClient.disconnect(); } } catch (IOException e) { throw new FTPClientException("Could not disconnect from server.", e); } } }
客户端测试方法:
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()); pool.returnResource(ftpClient); } System.out.println("time:"+(System.currentTimeMillis()-begin)); System.out.println("borrowSize2:"+pool.borrowSize()); System.out.println("inPoolSize2:"+pool.inPoolSize()); pool.destroy(); }