import java.io.IOException;
import java.util.NoSuchElementException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
/**
* 实现了一个FTPClient连接池
*
* @author moyesen
* @date 2019/6/21
*/
public class FTPClientPool implements ObjectPool<FTPClient> {
private static final int DEFAULT_POOL_SIZE = 10;
private final BlockingQueue<FTPClient> pool;
private final FTPClientFactory factory;
/**
* 初始化连接池,需要注入一个工厂来提供FTPClient实例
*
* @param factory
* @throws Exception
*/
public FTPClientPool(FTPClientFactory factory) throws Exception {
this(DEFAULT_POOL_SIZE, factory);
}
/**
* @param poolSize
* @param factory
* @throws Exception
*/
public FTPClientPool(int poolSize, FTPClientFactory factory) throws Exception {
this.factory = factory;
pool = new ArrayBlockingQueue<FTPClient>(poolSize * 2);
initPool(poolSize);
}
/**
* 初始化连接池,需要注入一个工厂来提供FTPClient实例
*
* @param maxPoolSize
* @throws Exception
*/
private void initPool(int maxPoolSize) throws Exception {
for (int i = 0; i < maxPoolSize; i++) {
//往池中添加对象
addObject();
}
}
/**
* 从连接池中获取对象
*
* @return
* @throws Exception
* @throws NoSuchElementException
* @throws IllegalStateException
*/
@Override
public FTPClient borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
FTPClient client = pool.take();
//验证不通过
if (!factory.validateObject(client)) {
//使对象在池中失效
invalidateObject(client);
//制造并添加新对象到池中
client = factory.makeObject();
addObject();
}
return client;
}
/**
* 返还对象到连接池中
*
* @param client
* @throws Exception
*/
@Override
public void returnObject(FTPClient client) throws Exception {
if ((client != null) && !pool.offer(client, 3, TimeUnit.SECONDS)) {
try {
factory.destroyObject(client);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 移除无效的客户端
*
* @param client
* @throws Exception
*/
@Override
public void invalidateObject(FTPClient client) throws Exception {
pool.remove(client);
}
/**
* 插入对象到队列
*
* @throws Exception
* @throws IllegalStateException
* @throws UnsupportedOperationException
*/
@Override
public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
pool.offer(factory.makeObject(), 3, TimeUnit.SECONDS);
}
/**
* 获取懒惰线程数
*
* @return
* @throws UnsupportedOperationException
*/
@Override
public int getNumIdle() throws UnsupportedOperationException {
return -1;
}
/**
* 获取激活线程数
*
* @return
* @throws UnsupportedOperationException
*/
@Override
public int getNumActive() throws UnsupportedOperationException {
return -1;
}
@Override
public void clear() throws Exception, UnsupportedOperationException {
}
/**
* 关闭连接池
*
* @throws Exception
*/
@Override
public void close() throws Exception {
while (pool.iterator().hasNext()) {
FTPClient client = pool.take();
factory.destroyObject(client);
}
}
@Override
public void setFactory(PoolableObjectFactory<FTPClient> poolableObjectFactory) throws IllegalStateException, UnsupportedOperationException {
}
}
//---------------------------------------美丽分割线------------------------------------------------------------------------------美丽分割线-------------------------------------------------------------------------------
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.pool.PoolableObjectFactory;
/**
* FTPClient工厂类,通过FTPClient工厂提供FTPClient实例的创建和销毁
*
* @author moyese
* @date 2019/6/21
*/
@Slf4j
public class FTPClientFactory implements PoolableObjectFactory<FTPClient> {
private FTPClientConfigure config;
/**
* 给工厂传入一个参数对象,方便配置FTPClient的相关参数
*
* @param config
*/
public FTPClientFactory(FTPClientConfigure config) {
this.config = config;
}
/**
* 创建FtpClient对象
*
* @return
* @throws Exception
*/
@Override
public FTPClient makeObject() throws Exception {
FTPClient ftpClient = new FTPClient();
ftpClient.setConnectTimeout(config.getClientTimeout());
try {
ftpClient.connect(config.getHost(), config.getPort());
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
log.warn("FTPServer refused connection");
return null;
}
boolean result = ftpClient.login(config.getUsername(), config.getPassword());
if (!result) {
throw new FTPClientException("ftpClient登陆失败! userName:" + config.getUsername() + " ; password:" + config.getPassword());
}
ftpClient.setFileType(config.getTransferFileType());
ftpClient.setBufferSize(1024);
ftpClient.setControlEncoding(config.getEncoding());
if (config.getPassiveMode()) {
ftpClient.enterLocalPassiveMode();
}
} catch (IOException e) {
e.printStackTrace();
} catch (FTPClientException e) {
e.printStackTrace();
}
return ftpClient;
}
/**
* 销毁FtpClient对象
*
* @param ftpClient
* @throws Exception
*/
@Override
public void destroyObject(FTPClient ftpClient) throws Exception {
try {
if (ftpClient != null && ftpClient.isConnected()) {
ftpClient.logout();
}
} catch (IOException io) {
io.printStackTrace();
} finally {
// 注意,一定要在finally代码中断开连接,否则会导致占用ftp连接情况
try {
ftpClient.disconnect();
} catch (IOException io) {
io.printStackTrace();
}
}
}
/**
* 验证FtpClient对象
*
* @param ftpClient
* @return
*/
@Override
public boolean validateObject(FTPClient ftpClient) {
try {
return ftpClient.sendNoOp();
} catch (IOException e) {
throw new RuntimeException("Failed to validate client: " + e, e);
}
}
@Override
public void activateObject(FTPClient ftpClient) throws Exception {
}
@Override
public void passivateObject(FTPClient ftpClient) throws Exception {
}
}
//---------------------------------------美丽分割线------------------------------------------------------------------------------美丽分割线-------------------------------------------------------------------------------
/**
* FTPClientException
*
* @author moyesen
* @date 2019/6/21 14:11
*/
public class FTPClientException extends Exception {
public FTPClientException(String message) {
super(message);
}
}
//---------------------------------------美丽分割线------------------------------------------------------------------------------美丽分割线-------------------------------------------------------------------------------
import lombok.Data;
/**
* FTPClient配置类,封装了FTPClient的相关配置
*
* @author moyesen
* @date 2019/6/21 13:33
*/
@Data
public class FTPClientConfigure {
/**
* ftp地址
*/
private String host;
/**
* 端口号
*/
private Integer port;
/**
* 登录用户
*/
private String username;
/**
* 登录密码
*/
private String password;
/**
* 编码
*/
private String encoding;
/**
* 连接超时时间(秒)
*/
private Integer connectTimeout;
/**
* 缓冲大小
*/
private Integer bufferSize;
/**
* 传输文件类型
*/
private Integer transferFileType;
/**
* 被动模式
*/
private Boolean passiveMode;
/**
* 超时时间
*/
private int clientTimeout;
}
转载于:https://my.oschina.net/moyesen/blog/3071838