gpt4 book ai didi

Java FTPClient连接池的实现

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 29 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Java FTPClient连接池的实现由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

最近在写一个ftp上传工具,用到了apache的ftpclient,为了提高上传效率,我采用了多线程的方式,但是每个线程频繁的创建和销毁ftpclient对象势必会造成不必要的开销,因此,此处最好使用一个ftpclient连接池。仔细翻了一下apache的api,发现它并没有一个ftpclientpool的实现,所以,不得不自己写一个ftpclientpool。下面就大体介绍一下开发连接池的整个过程,供大家参考.

关于对象池 。

有些对象的创建开销是比较大的,比如数据库连接等。为了减少频繁创建、销毁对象带来的性能消耗,我们可以利用对象池的技术来实现对象的复用。对象池提供了一种机制,它可以管理对象池中对象的生命周期,提供了获取和释放对象的方法,可以让客户端很方便的使用对象池中的对象.

如果我们要自己实现一个对象池,一般需要完成如下功能:

1. 如果池中有可用的对象,对象池应当能返回给客户端 2. 客户端把对象放回池里后,可以对这些对象进行重用 3. 对象池能够创建新的对象来满足客户端不断增长的需求 4. 需要有一个正确关闭池的机制来结束对象的生命周期 。

apache的对象池工具包 。

为了方便我们开发自己的对象池,apache 提供的common-pool工具包,里面包含了开发通用对象池的一些接口和实现类。其中最基本的两个接口是objectpool 和poolableobjectfactory.

objectpool接口中有几个最基本的方法:

1. addobject() : 添加对象到池 2. borrowobject():客户端从池中借出一个对象 3. returnobject():客户端归还一个对象到池中 4. close():关闭对象池,清理内存释放资源等 5. setfactory(objectfactory factory):需要一个工厂来制造池中的对象 。

poolableobjectfactory接口中几个最基本的方法:

1. makeobject():制造一个对象 2. destoryobject():销毁一个对象 3. validateobject():验证一个对象是否还可用 。

通过以上两个接口我们就可以自己实现一个对象池了.

实例:开发一个ftpclient对象池 。

最近在开发一个项目,需要把hdfs中的文件上传到一组ftp服务器,为了提高上传效率,自然考虑到使用多线程的方式进行上传。我上传ftp用的工具是apache common-net包中的ftpclient,但apache并没有提供ftpclientpool,于是为了减少ftpclient的创建销毁次数,我们就自己开发一个ftpclientpool来复用ftpclient连接.

通过上面的介绍,我们可以利用apache提供的common-pool包来协助我们开发连接池。而开发一个简单的对象池,仅需要实现common-pool 包中的objectpool和poolableobjectfactory两个接口即可。下面就看一下我写的实现:

写一个objectpool接口的实现ftpclientpool 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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 heaven
*/
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 maxpoolsize
  * @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();
    }
 
  }
  /* (non-javadoc)
  * @see org.apache.commons.pool.objectpool#borrowobject()
  */
  public ftpclient borrowobject() throws exception, nosuchelementexception, illegalstateexception {
    ftpclient client = pool.take();
    if (client == null) {
       client = factory.makeobject();
       addobject();
    }else if(!factory.validateobject(client)){//验证不通过
       //使对象在池中失效
       invalidateobject(client);
       //制造并添加新对象到池中
       client = factory.makeobject();
       addobject();
    }
    return client;
 
  }
 
  /* (non-javadoc)
  * @see org.apache.commons.pool.objectpool#returnobject(java.lang.object)
  */
  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();
       }
    }
  }
 
  public void invalidateobject(ftpclient client) throws exception {
    //移除无效的客户端
    pool.remove(client);
  }
 
  /* (non-javadoc)
  * @see org.apache.commons.pool.objectpool#addobject()
  */
  public void addobject() throws exception, illegalstateexception, unsupportedoperationexception {
    //插入对象到队列
    pool.offer(factory.makeobject(),3,timeunit.seconds);
  }
 
  public int getnumidle() throws unsupportedoperationexception {
    return 0;
  }
 
  public int getnumactive() throws unsupportedoperationexception {
    return 0;
  }
 
  public void clear() throws exception, unsupportedoperationexception {
 
  }
 
  /* (non-javadoc)
  * @see org.apache.commons.pool.objectpool#close()
  */
  public void close() throws exception {
    while (pool.iterator().hasnext()){
       ftpclient client = pool.take();
       factory.destroyobject(client);
    }
  }
 
  public void setfactory(poolableobjectfactory<ftpclient> factory) throws illegalstateexception, unsupportedoperationexception {
 
  }
}

再写一个poolableobjectfactory接口的实现ftpclientfactory 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import java.io.ioexception;
import org.apache.commons.net.ftp.ftpclient;
import org.apache.commons.net.ftp.ftpreply;
import org.apache.commons.pool.poolableobjectfactory;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
 
import com.hdfstoftp.util.ftpclientexception;
 
/**
* ftpclient工厂类,通过ftpclient工厂提供ftpclient实例的创建和销毁
* @author heaven
*/
public class ftpclientfactory implements poolableobjectfactory<ftpclient> {
private static logger logger = loggerfactory.getlogger( "file" );
  private ftpclientconfigure config;
  //给工厂传入一个参数对象,方便配置ftpclient的相关参数
  public ftpclientfactory(ftpclientconfigure config){
    this .config=config;
  }
 
  /* (non-javadoc)
  * @see org.apache.commons.pool.poolableobjectfactory#makeobject()
  */
  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();
         logger.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().equals("true")) {
         ftpclient.enterlocalpassivemode();
       }
    } catch (ioexception e) {
       e.printstacktrace();
    } catch (ftpclientexception e) {
       e.printstacktrace();
    }
    return ftpclient;
  }
 
  /* (non-javadoc)
  * @see org.apache.commons.pool.poolableobjectfactory#destroyobject(java.lang.object)
  */
  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();
       }
    }
  }
 
  /* (non-javadoc)
  * @see org.apache.commons.pool.poolableobjectfactory#validateobject(java.lang.object)
  */
  public boolean validateobject(ftpclient ftpclient) {
    try {
       return ftpclient.sendnoop();
    } catch (ioexception e) {
       throw new runtimeexception( "failed to validate client: " + e, e);
    }
  }
 
  public void activateobject(ftpclient ftpclient) throws exception {
  }
 
  public void passivateobject(ftpclient ftpclient) throws exception {
 
  }
}

最后,我们最好给工厂传递一个参数对象,方便我们设置ftpclient的一些参数 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package org.apache.commons.pool.impl.contrib;
 
/**
  * ftpclient配置类,封装了ftpclient的相关配置
  *
  * @author heaven
  */
public class ftpclientconfigure {
  private string host;
  private int port;
  private string username;
  private string password;
  private string passivemode;
  private string encoding;
  private int clienttimeout;
  private int threadnum;
  private int transferfiletype;
  private boolean renameuploaded;
  private int retrytimes;
 
  public string gethost() {
      return host;
  }
 
  public void sethost(string host) {
      this . host = host;
  }
 
  public int getport() {
      return port;
  }
 
  public void setport( int port) {
      this . port = port;
  }
 
  public string getusername() {
      return username;
  }
 
  public void setusername(string username) {
      this . username = username;
  }
 
  public string getpassword() {
      return password;
  }
 
  public void setpassword(string password) {
      this . password = password;
  }
 
 
  public string getpassivemode() {
      return passivemode;
  }
 
  public void setpassivemode(string passivemode) {
      this . passivemode = passivemode;
  }
 
  public string getencoding() {
      return encoding;
  }
 
  public void setencoding(string encoding) {
      this . encoding = encoding;
  }
 
  public int getclienttimeout() {
      return clienttimeout;
  }
 
  public void setclienttimeout( int clienttimeout) {
      this . clienttimeout = clienttimeout;
  }
 
  public int getthreadnum() {
      return threadnum;
  }
 
  public void setthreadnum( int threadnum) {
      this . threadnum = threadnum;
  }
 
  public int gettransferfiletype() {
      return transferfiletype;
  }
 
  public void settransferfiletype( int transferfiletype) {
      this . transferfiletype = transferfiletype;
  }
 
  public boolean isrenameuploaded() {
      return renameuploaded;
  }
 
  public void setrenameuploaded( boolean renameuploaded) {
      this . renameuploaded = renameuploaded;
  }
 
  public int getretrytimes() {
      return retrytimes;
  }
 
  public void setretrytimes( int retrytimes) {
      this . retrytimes = retrytimes;
  }
 
  @override
  public string tostring() {
      return "ftpclientconfig [host=" + host + "\n port=" + port + "\n username=" + username + "\n password=" + password  + "\n passivemode=" + passivemode
           + "\n encoding=" + encoding + "\n clienttimeout=" + clienttimeout + "\n threadnum=" + threadnum + "\n transferfiletype="
           + transferfiletype + "\n renameuploaded=" + renameuploaded + "\n retrytimes=" + retrytimes + "]" ;
  }
 
}

 ftpclientpool连接池类管理ftpclient对象的生命周期,负责对象的借出、规划、池的销毁等;ftpclientpool类依赖于ftpclientfactory类,由这个工程类来制造和销毁对象;ftpclientfactory又依赖ftpclientconfigure类,ftpclientconfigure负责封装ftpclient的配置参数。至此,我们的ftpclient连接池就开发完成了.

需要注意的是,ftpclientpool中用到了一个阻塞队列arrayblockingqueue来管理存放ftpclient对象,关于阻塞队列,请参考我的这篇文章: 【java并发之】blockingqueue 。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.

原文链接:https://blog.csdn.net/suifeng3051/article/details/48969679 。

最后此篇关于Java FTPClient连接池的实现的文章就讲到这里了,如果你想了解更多关于Java FTPClient连接池的实现的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com