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);
}
}
相关推荐
使用apache的commons-pool2 构建 FTPClient连接池 有FtpClientFactory、FtpClientPool、FtpConfig、FtpOperate 四个类组成 还有ftp连接池的一些配置参数信息在ftp.properties文件中 注释完整欢迎大家下载使用
Java FTPClient连接池的实现 在这篇文章中,我们主要介绍了Java FTPClient连接池的实现。首先,我们需要了解为什么需要使用连接池。创建和销毁FTPClient对象是非常耗费资源的操作,因此,我们可以使用连接池来复用...
本文将深入探讨如何在Spring Boot项目中集成FTP连接池,以解决并发用户上传附件时的性能问题。 首先,我们需要引入相关的依赖。在Spring Boot项目中,可以使用Apache Commons Net库来实现FTP功能,并使用Apache ...
在 Spring Boot 项目中,我们可以使用 Apache 的 common-pool 包来协助我们开发连接池。具体来说,我们需要实现 common-pool 包中的 ObjectPool 和 PoolableObjectFactory 两个接口。 首先,我们需要在 pom 文件中...
在这个工具中,可能会封装上述的基本FTP操作,并可能提供更友好的API,如异步处理、错误处理、连接池管理等功能,以简化开发者的使用。 总结一下,`FtpClient`是Java中实现FTP功能的重要工具,它提供了丰富的接口来...
Java提供了内置的`java.net.FTPClient`类来处理FTP连接。以下是一个基本的FTP连接和文件上传示例: ```java import java.io.*; import org.apache.commons.net.ftp.*; public class FTPExample { public ...
同时,为了处理异常和优化性能,还会考虑使用连接池、重试机制、断点续传等功能。 总的来说,通过结合`commons-net-1.4.1.jar`和`jakarta-oro-2.0.8.jar`这两个库,Java开发者可以构建出强大且灵活的FTP客户端应用...
另一个可能进行了二次封装,意味着它在基础功能之上添加了更高级的功能,比如错误处理、连接池管理或者更友好的API,以提高代码的可读性和复用性。 在JDK 1.7版本中,Java已经内置了`java.net.FTPSClient`和`java...
`FTPNet.java`可能包含了`FTPClient`的使用逻辑,而`FtpConManager.java`可能是一个管理FTP连接的类,用于控制连接池,确保资源的有效管理和复用。 `FTPNet.java`可能包含以下关键方法: - `connectToFtpServer...
此外,考虑到FTP服务器可能有并发限制,我们需要管理好连接池,避免过多的并发连接导致服务器拒绝服务。 总的来说,Java实现的FTP连接与数据浏览程序涉及网络编程、文件操作、流处理、错误处理等多个方面的知识。...
9. **性能优化**:通过缓存策略、负载均衡、连接池等技术,可以优化Java网络通讯系统的性能,提高响应速度和并发处理能力。 10. **测试与调试**:单元测试、集成测试和压力测试是保证网络通讯系统质量的关键步骤。...
此外,如果需要处理大量文件或频繁的FTP操作,考虑使用多线程和连接池以提高性能。 总之,Java FTP功能为我们提供了一种可靠的方式来与FTP服务器交互,无论是下载文件还是读取内容,都是业务系统中常见且实用的功能...
在IT行业中,FTP(File Transfer Protocol)是一种广泛用于在互联网上进行文件传输的标准协议。Java作为一种多用途且跨...在实际开发中,根据项目需求,可能还需要考虑更多细节,如连接池管理、线程安全、重试策略等。
高级的下载器可能还会涉及连接池的使用,以减少建立和关闭Socket的开销;或者使用NIO(非阻塞I/O)来提高性能。Java的`java.nio`包提供了这些功能的支持。 通过研究和实践这个Java网络编程下载器源代码,学习者可以...
此外,Apache HttpClient库提供更高级的功能,如多线程、连接池和自定义请求头。 4. **FTP协议**:文件传输协议(FTP)用于在网络上进行文件传输。Java通过java.net.FTPSClient和java.net.FTPClient类提供了FTP和...
10. **性能优化**:可以通过缓存优化、连接池管理等方式提升下载性能。例如,使用HTTP/1.1的Keep-Alive特性保持连接,减少握手开销;或者使用线程池避免频繁创建销毁线程。 综上所述,"Http下载器 FTP下载器(java...
它支持文件上传和下载,提供了异步和同步的API,以及连接池和重试策略。 6. **FTP/FTPS**:如果需要与FTP或安全的FTPS服务器交互,可以使用`java.net`包中的`FTPClient`类,或者使用第三方库如Apache Commons Net。...
- `java.net.Socket`:创建TCP连接,是FTP通信的基础。 - `java.io.InputStream`和`OutputStream`:读写文件的数据流。 - `java.io.BufferedReader`和`PrintWriter`:处理FTP命令的输入和输出。 2. **FTP基本...
同时,考虑使用连接池管理FTP连接,以提高性能和资源利用效率。此外,使用异步或多线程处理文件传输可以提高上传和下载的速度。 总之,Java通过Apache Commons Net库与FTP服务器交互,可以方便地实现文件的上传、...