最近在写一个FTP上传工具,用到了Apache的FTPClient,但是每个线程频繁的创建和销毁FTPClient对象对服务器的压力很大,因此,此处最好使用一个FTPClient连接池。仔细翻了一下Apache的api,发现它并没有一个FTPClientPool的实现,所以,不得不自己写一个FTPClientPool。下面就大体介绍一下开发连接池的整个过程,供大家参考。
我们可以利用Apache提供的common-pool包来协助我们开发连接池。而开发一个简单的对象池,仅需要实现common-pool 包中的ObjectPool和PoolableObjectFactory两个接口即可。
线程池的意义
为了减少频繁创建、销毁对象带来的性能消耗,我们可以利用对象池的技术来实现对象的复用。对象池提供了一种机制,它可以管理对象池中对象的生命周期,提供了获取和释放对象的方法,可以让客户端很方便的使用对象池中的对象。
pom引入依赖
commons-net
commons-net
3.5
commons-pool
commons-pool
1.6
org.apache.commons
commons-pool2
2.0
创建ftp配置信息
在resources目录下创建ftp.properties配置文件,目录结构如下:
添加如下的配置信息:
########### FTP用户名称 ###########
ftp.userName=hrabbit
########### FTP用户密码 ###########
ftp.passWord=123456
########### FTP主机IP ###########
ftp.host=127.0.0.1
########### FTP主机端口号 ###########
ftp.port=21
########### 保存根路径 ###########
ftp.baseUrl=/
创建FTPProperties.java配置文件
加载配置内容到Spring中,配置信息基本延用我的就可以。
/**
* FTP的配置信息
* @Auther: hrabbit
* @Date: 2018-12-03 2:06 PM
* @Description:
*/
@Data
@Component
@PropertySource("classpath:ftp.properties")
@ConfigurationProperties(prefix = "ftp")
public class FTPProperties {
private String username;
private String password;
private String host;
private Integer port;
private String baseUrl;
private Integer passiveMode = FTP.BINARY_FILE_TYPE;
private String encoding="UTF-8";
private int clientTimeout=120000;
private int bufferSize;
private int transferFileType=FTP.BINARY_FILE_TYPE;
private boolean renameUploaded;
private int retryTime;
}
创建FTPClientPool线程池
/**
* 自定义实现ftp连接池
* @Auther: hrabbit
* @Date: 2018-12-03 3:40 PM
* @Description:
*/
@Slf4j
@SuppressWarnings("all")
public class FTPClientPool implements ObjectPool {
private static final int DEFAULT_POOL_SIZE = 10;
public BlockingQueue 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(poolSize);
initPool(poolSize);
}
/**
* 初始化连接池
* @param maxPoolSize
* 最大连接数
* @throws Exception
*/
private void initPool(int maxPoolSize) throws Exception {
int count = 0;
while(count < maxPoolSize) {
this.addObject();
count++;
}
}
/**
* 从连接池中获取对象
*/