欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java FTPClient連接池的實(shí)現(xiàn)

 更新時(shí)間:2018年06月26日 10:25:29   作者:Heaven-Wang  
這篇文章主要介紹了Java FTPClient連接池的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

最近在寫(xiě)一個(gè)FTP上傳工具,用到了Apache的FTPClient,為了提高上傳效率,我采用了多線程的方式,但是每個(gè)線程頻繁的創(chuàng)建和銷(xiāo)毀FTPClient對(duì)象勢(shì)必會(huì)造成不必要的開(kāi)銷(xiāo),因此,此處最好使用一個(gè)FTPClient連接池。仔細(xì)翻了一下Apache的api,發(fā)現(xiàn)它并沒(méi)有一個(gè)FTPClientPool的實(shí)現(xiàn),所以,不得不自己寫(xiě)一個(gè)FTPClientPool。下面就大體介紹一下開(kāi)發(fā)連接池的整個(gè)過(guò)程,供大家參考。

關(guān)于對(duì)象池

有些對(duì)象的創(chuàng)建開(kāi)銷(xiāo)是比較大的,比如數(shù)據(jù)庫(kù)連接等。為了減少頻繁創(chuàng)建、銷(xiāo)毀對(duì)象帶來(lái)的性能消耗,我們可以利用對(duì)象池的技術(shù)來(lái)實(shí)現(xiàn)對(duì)象的復(fù)用。對(duì)象池提供了一種機(jī)制,它可以管理對(duì)象池中對(duì)象的生命周期,提供了獲取和釋放對(duì)象的方法,可以讓客戶(hù)端很方便的使用對(duì)象池中的對(duì)象。

如果我們要自己實(shí)現(xiàn)一個(gè)對(duì)象池,一般需要完成如下功能:

1. 如果池中有可用的對(duì)象,對(duì)象池應(yīng)當(dāng)能返回給客戶(hù)端
2. 客戶(hù)端把對(duì)象放回池里后,可以對(duì)這些對(duì)象進(jìn)行重用
3. 對(duì)象池能夠創(chuàng)建新的對(duì)象來(lái)滿足客戶(hù)端不斷增長(zhǎng)的需求
4. 需要有一個(gè)正確關(guān)閉池的機(jī)制來(lái)結(jié)束對(duì)象的生命周期

Apache的對(duì)象池工具包

為了方便我們開(kāi)發(fā)自己的對(duì)象池,Apache 提供的common-pool工具包,里面包含了開(kāi)發(fā)通用對(duì)象池的一些接口和實(shí)現(xiàn)類(lèi)。其中最基本的兩個(gè)接口是ObjectPool 和PoolableObjectFactory。

ObjectPool接口中有幾個(gè)最基本的方法:

1. addObject() : 添加對(duì)象到池
2. borrowObject():客戶(hù)端從池中借出一個(gè)對(duì)象
3. returnObject():客戶(hù)端歸還一個(gè)對(duì)象到池中
4. close():關(guān)閉對(duì)象池,清理內(nèi)存釋放資源等
5. setFactory(ObjectFactory factory):需要一個(gè)工廠來(lái)制造池中的對(duì)象

PoolableObjectFactory接口中幾個(gè)最基本的方法:

1. makeObject():制造一個(gè)對(duì)象
2. destoryObject():銷(xiāo)毀一個(gè)對(duì)象
3. validateObject():驗(yàn)證一個(gè)對(duì)象是否還可用

通過(guò)以上兩個(gè)接口我們就可以自己實(shí)現(xiàn)一個(gè)對(duì)象池了。

實(shí)例:開(kāi)發(fā)一個(gè)FTPClient對(duì)象池

最近在開(kāi)發(fā)一個(gè)項(xiàng)目,需要把hdfs中的文件上傳到一組ftp服務(wù)器,為了提高上傳效率,自然考慮到使用多線程的方式進(jìn)行上傳。我上傳ftp用的工具是Apache common-net包中的FTPClient,但Apache并沒(méi)有提供FTPClientPool,于是為了減少FTPClient的創(chuàng)建銷(xiāo)毀次數(shù),我們就自己開(kāi)發(fā)一個(gè)FTPClientPool來(lái)復(fù)用FTPClient連接。

通過(guò)上面的介紹,我們可以利用Apache提供的common-pool包來(lái)協(xié)助我們開(kāi)發(fā)連接池。而開(kāi)發(fā)一個(gè)簡(jiǎn)單的對(duì)象池,僅需要實(shí)現(xiàn)common-pool 包中的ObjectPool和PoolableObjectFactory兩個(gè)接口即可。下面就看一下我寫(xiě)的實(shí)現(xiàn):

寫(xiě)一個(gè)ObjectPool接口的實(shí)現(xiàn)FTPClientPool

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;

/**
* 實(shí)現(xiàn)了一個(gè)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;

 /**
 * 初始化連接池,需要注入一個(gè)工廠來(lái)提供FTPClient實(shí)例
 * @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);
 }
 /**
 * 初始化連接池,需要注入一個(gè)工廠來(lái)提供FTPClient實(shí)例
 * @param maxPoolSize
 * @throws Exception
 */
 private void initPool(int maxPoolSize) throws Exception {
   for(int i=0;i<maxPoolSize;i++){
      //往池中添加對(duì)象
      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)){//驗(yàn)證不通過(guò)
      //使對(duì)象在池中失效
      invalidateObject(client);
      //制造并添加新對(duì)象到池中
      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 {
   //移除無(wú)效的客戶(hù)端
   pool.remove(client);
 }

 /* (non-Javadoc)
 * @see org.apache.commons.pool.ObjectPool#addObject()
 */
 public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
   //插入對(duì)象到隊(duì)列
   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 {

 }
}

再寫(xiě)一個(gè)PoolableObjectFactory接口的實(shí)現(xiàn)FTPClientFactory

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工廠類(lèi),通過(guò)FTPClient工廠提供FTPClient實(shí)例的創(chuàng)建和銷(xiāo)毀
* @author heaven
*/
public class FtpClientFactory implements PoolableObjectFactory<FTPClient> {
private static Logger logger = LoggerFactory.getLogger("file");
 private FTPClientConfigure config;
 //給工廠傳入一個(gè)參數(shù)對(duì)象,方便配置FTPClient的相關(guān)參數(shù)
 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代碼中斷開(kāi)連接,否則會(huì)導(dǎo)致占用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 {

 }
}

最后,我們最好給工廠傳遞一個(gè)參數(shù)對(duì)象,方便我們?cè)O(shè)置FTPClient的一些參數(shù)

package org.apache.commons.pool.impl.contrib;

/**
 * FTPClient配置類(lèi),封裝了FTPClient的相關(guān)配置
 *
 * @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連接池類(lèi)管理FTPClient對(duì)象的生命周期,負(fù)責(zé)對(duì)象的借出、規(guī)劃、池的銷(xiāo)毀等;FTPClientPool類(lèi)依賴(lài)于FtpClientFactory類(lèi),由這個(gè)工程類(lèi)來(lái)制造和銷(xiāo)毀對(duì)象;FtpClientFactory又依賴(lài)FTPClientConfigure類(lèi),F(xiàn)TPClientConfigure負(fù)責(zé)封裝FTPClient的配置參數(shù)。至此,我們的FTPClient連接池就開(kāi)發(fā)完成了。

需要注意的是,F(xiàn)TPClientPool中用到了一個(gè)阻塞隊(duì)列ArrayBlockingQueue來(lái)管理存放FTPClient對(duì)象,關(guān)于阻塞隊(duì)列,請(qǐng)參考我的這篇文章: 【Java并發(fā)之】BlockingQueue

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java?Export大量數(shù)據(jù)導(dǎo)出和打包

    java?Export大量數(shù)據(jù)導(dǎo)出和打包

    這篇文章主要為大家介紹了java?Export大量數(shù)據(jù)的導(dǎo)出和打包實(shí)現(xiàn)過(guò)程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Spring Boot 從靜態(tài)json文件中讀取數(shù)據(jù)所需字段

    Spring Boot 從靜態(tài)json文件中讀取數(shù)據(jù)所需字段

    本文重點(diǎn)給大家介紹Spring Boot 從靜態(tài)json文件中讀取數(shù)據(jù)所需字段,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2018-05-05
  • Java8新特性之lambda的作用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java8新特性之lambda的作用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    我們期待了很久lambda為java帶來(lái)閉包的概念,但是如果我們不在集合中使用它的話,就損失了很大價(jià)值?,F(xiàn)有接口遷移成為lambda風(fēng)格的問(wèn)題已經(jīng)通過(guò)default methods解決了,在這篇文章將深入解析Java集合里面的批量數(shù)據(jù)操作解開(kāi)lambda最強(qiáng)作用的神秘面紗。
    2017-06-06
  • SpringBoot使用GTS的示例詳解

    SpringBoot使用GTS的示例詳解

    這篇文章主要介紹了SpringBoot使用GTS的示例詳解,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • 淺談springboot一個(gè)service內(nèi)組件的加載順序

    淺談springboot一個(gè)service內(nèi)組件的加載順序

    這篇文章主要介紹了springboot一個(gè)service內(nèi)組件的加載順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家
    2021-08-08
  • Java編程使用Runtime和Process類(lèi)運(yùn)行外部程序的方法

    Java編程使用Runtime和Process類(lèi)運(yùn)行外部程序的方法

    這篇文章主要介紹了Java編程使用Runtime和Process類(lèi)運(yùn)行外部程序的方法,結(jié)合實(shí)例形式分析了java使用Runtime.getRuntime().exec()方法運(yùn)行外部程序的常見(jiàn)情況與操作技巧,需要的朋友可以參考下
    2017-08-08
  • SpringBoot集成echarts實(shí)現(xiàn)k線圖功能

    SpringBoot集成echarts實(shí)現(xiàn)k線圖功能

    ECharts是一款基于JavaScript的數(shù)據(jù)可視化圖表庫(kù),提供直觀,生動(dòng),可交互,可個(gè)性化定制的數(shù)據(jù)可視化圖表,本文給大家介紹了SpringBoot集成echarts實(shí)現(xiàn)k線圖功能,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下
    2024-07-07
  • spring中@autowired、@Qualifier、@Primary注解的使用說(shuō)明

    spring中@autowired、@Qualifier、@Primary注解的使用說(shuō)明

    這篇文章主要介紹了spring中@autowired、@Qualifier、@Primary注解的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java實(shí)現(xiàn)字符串切割的方法詳解

    Java實(shí)現(xiàn)字符串切割的方法詳解

    這篇文章主要為大家介紹了一些Java中切割字符串的小技巧,可以把性能提升5~10倍。文中的示例代碼講解詳細(xì),快跟隨小編一起學(xué)習(xí)一下
    2022-03-03
  • 對(duì)SpringBoot項(xiàng)目Jar包進(jìn)行加密防止反編譯的方案

    對(duì)SpringBoot項(xiàng)目Jar包進(jìn)行加密防止反編譯的方案

    最近項(xiàng)目要求部署到其他公司的服務(wù)器上,但是又不想將源碼泄露出去,要求對(duì)正式環(huán)境的啟動(dòng)包進(jìn)行安全性處理,防止客戶(hù)直接通過(guò)反編譯工具將代碼反編譯出來(lái),本文介紹了如何對(duì)SpringBoot項(xiàng)目Jar包進(jìn)行加密防止反編譯,需要的朋友可以參考下
    2024-08-08

最新評(píng)論