VSFTP之创建连接池

场景:原有老项目的文件系统进行优化,以应对高并发

1、导入maven依赖

<dependency>
      <groupId>commons-net</groupId>
      <artifactId>commons-net</artifactId>
      <version>3.3</version>
      <classifier>ftp</classifier>
</dependency>
<dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      <version>2.4.2</version>
</dependency>

2、FtpPoolConfig.java:ftp配置参数对象 继承自GenericObjectPoolConfig

public class FtpPoolConfig extends GenericObjectPoolConfig {
    
    private  String host = "192.168.0.***";//主机名
    private  int port=21;//端口
    private  String username = "***";//用户名
    private   String password = "***";//密码
    
    private int  connectTimeOut=5000;//ftp 连接超时时间 毫秒
    private String  controlEncoding="utf-8";
    private int  bufferSize  =1024;//缓冲区大小
    private  int  fileType =2  ;//  传输数据格式   2表binary二进制数据
    private  int  dataTimeout=  120000;
    private   boolean  useEPSVwithIPv4 =false;
    private  boolean  passiveMode =true;//是否启用被动模式
    
   
	public int getConnectTimeOut() {
		return connectTimeOut;
	}
	public void setConnectTimeOut(int connectTimeOut) {
		this.connectTimeOut = connectTimeOut;
	}
	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 getControlEncoding() {
		return controlEncoding;
	}
	public void setControlEncoding(String controlEncoding) {
		this.controlEncoding = controlEncoding;
	}
	public int getBufferSize() {
		return bufferSize;
	}
	public void setBufferSize(int bufferSize) {
		this.bufferSize = bufferSize;
	}
	 
	public int getFileType() {
		return fileType;
	}
	public void setFileType(int fileType) {
		this.fileType = fileType;
	}
	public int getDataTimeout() {
		return dataTimeout;
	}
	public void setDataTimeout(int dataTimeout) {
		this.dataTimeout = dataTimeout;
	}
	public boolean isUseEPSVwithIPv4() {
		return useEPSVwithIPv4;
	}
	public void setUseEPSVwithIPv4(boolean useEPSVwithIPv4) {
		this.useEPSVwithIPv4 = useEPSVwithIPv4;
	}
	public boolean isPassiveMode() {
		return passiveMode;
	}
	public void setPassiveMode(boolean passiveMode) {
		this.passiveMode = passiveMode;
	}

}

3、ftpclient 工厂

public class FTPClientFactory extends BasePooledObjectFactory<FTPClient> {
	
    private static Logger logger =Logger.getLogger(FTPClientFactory.class);
    
    private FtpPoolConfig ftpPoolConfig;
    
     
   
	public FtpPoolConfig getFtpPoolConfig() {
		return ftpPoolConfig;
	}
 
	public void setFtpPoolConfig(FtpPoolConfig ftpPoolConfig) {
		this.ftpPoolConfig = ftpPoolConfig;
	}
 
	/**
     * 新建对象
     */
    @Override
    public FTPClient create() throws Exception {
        FTPClient ftpClient = new FTPClient();
        ftpClient.setConnectTimeout(ftpPoolConfig.getConnectTimeOut());
        try {
        	
        	logger.info("连接ftp服务器:" +ftpPoolConfig.getHost()+":"+ftpPoolConfig.getPort());
        	ftpClient.connect(ftpPoolConfig.getHost(), ftpPoolConfig.getPort());
            
            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                logger.error("FTPServer 拒绝连接");
                return null;
            }
            boolean result = ftpClient.login(ftpPoolConfig.getUsername(),ftpPoolConfig.getPassword());
            if (!result) {
                logger.error("ftpClient登录失败!");
                throw new Exception("ftpClient登录失败! userName:"+ ftpPoolConfig.getUsername() + ", password:"
                        + ftpPoolConfig.getPassword());
            }
         
			ftpClient.setControlEncoding(ftpPoolConfig.getControlEncoding());
			ftpClient.setBufferSize(ftpPoolConfig.getBufferSize());
			ftpClient.setFileType(ftpPoolConfig.getFileType());
			ftpClient.setDataTimeout(ftpPoolConfig.getDataTimeout());
			ftpClient.setUseEPSVwithIPv4(ftpPoolConfig.isUseEPSVwithIPv4());
			if(ftpPoolConfig.isPassiveMode()){
				logger.info("进入ftp被动模式");
				ftpClient.enterLocalPassiveMode();//进入被动模式
			}
        } catch (IOException e) {
            logger.error("FTP连接失败:", e);
        }
        return ftpClient;
    }
 
    @Override
    public PooledObject<FTPClient> wrap(FTPClient ftpClient) {
        return new DefaultPooledObject<FTPClient>(ftpClient);
    }
 
    /**
     * 销毁对象
     */
    @Override
    public void destroyObject(PooledObject<FTPClient> p) throws Exception {
        FTPClient ftpClient = p.getObject();
        ftpClient.logout();
        super.destroyObject(p);
    }
 
    /**
     * 验证对象
     */
    @Override
    public boolean validateObject(PooledObject<FTPClient> p) {
        FTPClient ftpClient = p.getObject();
        boolean connect = false;
        try {
            connect = ftpClient.sendNoOp();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return connect;
    }
    
 
    /**
     *  No-op.
     *
     *  @param p ignored
     */
    @Override
    public void activateObject(PooledObject<FTPClient> p) throws Exception {
        // The default implementation is a no-op.
    }
 
    /**
     *  No-op.
     *
     * @param p ignored
     */
    @Override
    public void passivateObject(PooledObject<FTPClient> p)
        throws Exception {
        // The default implementation is a no-op.
    }
}

4、FTP 客户端连接池

public class FTPClientPool {
	
	/**
	 * ftp客户端连接池
	 */
    private GenericObjectPool<FTPClient> pool;
 
    /**
     * ftp客户端工厂
     */
    private       FTPClientFactory clientFactory;
    
    
     /**
      * 构造函数中 注入一个bean
      * 
      * @param clientFactory
      */
    public   FTPClientPool(  FTPClientFactory clientFactory){
	    this.clientFactory=clientFactory;
 	    pool = new GenericObjectPool<FTPClient>(clientFactory, clientFactory.getFtpPoolConfig());
	   
     }
     
    
	public FTPClientFactory getClientFactory() {
		return clientFactory;
	}
 
 
	public GenericObjectPool<FTPClient> getPool() {
		return pool;
	}
 
 
	/**
	 * 借  获取一个连接对象
	 * @return
	 * @throws Exception
	 */
    public FTPClient borrowObject() throws Exception {
    	
    	FTPClient  client =    pool.borrowObject();
    	
//    	if(!client.sendNoOp()){
//    		//使池中的对象无效 
//    		 client.logout();
//    		 client.disconnect();
//    		 pool.invalidateObject(client);
//    		 client =clientFactory.create();
//    		 pool.addObject();
//    	 }
//        
    	return client ;
    
    }
    /**
     * 还   归还一个连接对象
     * @param ftpClient
     */
    public void returnObject(FTPClient ftpClient) {
    	
    	if(ftpClient!=null){
    		pool.returnObject(ftpClient); 
    	}
    }
}

5、ftp客户端辅助bean

public class FTPClientHelper {
	
 
	private FTPClientPool  ftpClientPool;
	private FTPClientFactory  ftpClientFactory;
	private FtpPoolConfig  ftpPoolConfig;

    public void setFtpClientPool(FTPClientPool ftpClientPool) {
		this.ftpClientPool = ftpClientPool;
	}
	
    /**
     * 下载 remote文件流  
     * @param remote 远程文件
     * @return 字节数据
     * @throws Exception
     */
	public   byte[] retrieveFileStream(String remote) throws Exception {
		FTPClient client=null;
		InputStream in =null;
	    try {
	    	//  long start =System.currentTimeMillis();
	    	   client=	ftpClientPool.borrowObject();
	    	   in=client.retrieveFileStream(remote);
	    	//  long end =System.currentTimeMillis();
	    	 // System.out.println("ftp下载耗时(毫秒):"+(end-start));
	    	return   ByteUtil.inputStreamToByteArray(in);
		 }finally{
			  if (in != null) {  
	                in.close();  
	            } 
            if (!client.completePendingCommand()) {  
            	client.logout();  
            	client.disconnect();  
            	ftpClientPool.getPool().invalidateObject(client);
            } 
			ftpClientPool.returnObject(client);
			 
		}
	}
	
	/**
	 * 创建目录    单个不可递归
	 * @param pathname 目录名称
	 * @return
	 * @throws Exception
	 */
	public   boolean makeDirectory(String pathname) throws Exception {
		
		FTPClient client=null;
	    try {
			if(ftpClientPool==null) ftpClientPool = returnFTPClientPool(ftpClientPool);
			client = ftpClientPool.borrowObject();
			// 将路径中的斜杠统一
			char[] chars = pathname.toCharArray();
			StringBuffer sbStr = new StringBuffer(256);
			for (int i = 0; i < chars.length; i++) {
				if ('\\' == chars[i]) {
					sbStr.append('/');
				} else {
					sbStr.append(chars[i]);
				}
			}
			pathname = sbStr.toString();
			if (pathname.indexOf('/') == -1) {
				// 只有一层目录
				client.makeDirectory(new String(pathname.getBytes(), "iso-8859-1"));
				client.changeWorkingDirectory(new String(pathname.getBytes(), "iso-8859-1"));
			} else {
				// 多层目录循环创建
				String[] paths = pathname.split("/");
				for (int i = 0; i < paths.length; i++) {
					client.makeDirectory(new String(paths[i].getBytes(),"iso-8859-1"));
					client.changeWorkingDirectory(new String(paths[i].getBytes(), "iso-8859-1"));
				}
			}
			return true;
		}catch (Exception e){
	    	e.printStackTrace();
			return false;
		}  finally{
			ftpClientPool.returnObject(client);
		}
	}
	
	/**
	 * 删除目录,单个不可递归
	 * @param pathname
	 * @return
	 * @throws IOException
	 */
	public   boolean removeDirectory(String pathname) throws Exception {
		FTPClient client=null;
	    try {
	    	client=	ftpClientPool.borrowObject();
			return  client.removeDirectory(pathname);
		} finally{
			ftpClientPool.returnObject(client);
		}
	}
	
	/**
	 * 删除文件 单个 ,不可递归 
	 * @param pathname
	 * @return
	 * @throws Exception
	 */
	public   boolean deleteFile(String pathname) throws Exception {
		
		FTPClient client=null;
	    try {
	    	client=	ftpClientPool.borrowObject();
			return  client.deleteFile(pathname);
		}finally{
			ftpClientPool.returnObject(client);
		}
	}
	
	/**
	 * 上传文件 
	 * @param remote
	 * @param local
	 * @return
	 * @throws Exception
	 */
	public   boolean storeFile(String ftpDirectory,String remote, InputStream local) throws Exception {
		FTPClient client=null;
	    try {
	    	if(ftpClientPool==null) ftpClientPool = returnFTPClientPool(ftpClientPool);
	    	client=	ftpClientPool.borrowObject();
			makeDirectory(ftpDirectory);
			return client.storeFile(remote, local);
		} finally{
			ftpClientPool.returnObject(client);
		}
	}
	public FTPClientPool returnFTPClientPool(FTPClientPool ftpClientPool) throws Exception{
		if(ftpClientPool==null){
			if(ftpClientFactory==null){
				ftpClientFactory = new FTPClientFactory();
				if(ftpPoolConfig==null) ftpPoolConfig = new FtpPoolConfig();
				ftpClientFactory.setFtpPoolConfig(ftpPoolConfig);
				ftpClientFactory.create();
			}
			ftpClientPool = new FTPClientPool(ftpClientFactory);
		}
		return ftpClientPool;
	}

	public static void main(String[] args) throws Exception{
		FTPClientHelper ftpClientHelper = new FTPClientHelper();
		for(int i=0;i<1000;i++){
			boolean a = ftpClientHelper.storeFile("test","test/hahaha"+i+".png",new FileInputStream(new File("C:\\FileSystem\\72035b95379844a09506ab11b7f1edf3.png")));
			System.out.println(a);
			if(i==500){
				System.out.println(500+"-----------------------------------------");
			}
		}
	}
   
}

6、字节工具类

public class ByteUtil {
	
	 public static byte[] inputStreamToByteArray(InputStream in)  {
		 try {
			 ByteArrayOutputStream out=new ByteArrayOutputStream();
		        byte[] buffer=new byte[1024*4];
		        int n=0;
		        while ( (n=in.read(buffer)) >0) {
		            out.write(buffer,0,n);
		        }
		      return  out.toByteArray();
		       
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}  
	 }
 
}

7、效果:每次上传,都从连接池获取ftp连接

发布了130 篇原创文章 · 获赞 379 · 访问量 47万+

猜你喜欢

转载自blog.csdn.net/qq_31122833/article/details/103392050