开发目的:使用FTP连接池来管理FTP连接,以避免不断的连接FTP造成性能下降。
1、FTP连接池,建立一个java类FtpConnectionPooling
package com.dripstone.ftp; import java.util.concurrent.BlockingQueue; import java.util.concurrent.PriorityBlockingQueue; /** * <br>Title:FTP连接池 * <br>Description:FTP连接池及FTP连接池相应的操作 * <br>Author:张智研([email protected]) * <br>Date:2013-7-4 */ public abstract class FtpConnectionPooling { private static BlockingQueue<FtpClient> fqueue; private static FtpClientInfo ftpClientInfo; /** * <br>Description:初始化连接池 * <br>Author:张智研([email protected]) * <br>Date:2013-7-4 * @param ftpClientInfo */ public static void init(FtpClientInfo info) { ftpClientInfo = info; fqueue = new PriorityBlockingQueue<FtpClient>(ftpClientInfo.getMaxConnects(), new FtpClientComparator());// 初始化队列容量 FtpClient ftpClient; for (int i = 0; i < ftpClientInfo.getMaxConnects(); i++) { ftpClient = new FtpClient(); ftpClient.order = i; fqueue.add(ftpClient); } } public static FtpClientInfo getFtpClientInfo() { return ftpClientInfo; } /** * <br>Description:向线程池中添加FTPClient * <br>Author:张智研([email protected]) * <br>Date:2013-7-4 * @param ftpClient */ public static boolean add(FtpClient ftpClient) { boolean b = fqueue.contains(ftpClient); if (!b) return fqueue.add(ftpClient); return true; } /** * <br>Description:获取FTPClient,如果线程池为空,则等待到FtpClientInfo中所设置的超时时间 * <br>Author:张智研([email protected]) * <br>Date:2013-7-4 * @return * @throws InterruptedException */ public static FtpClient poll() throws InterruptedException { return fqueue.poll(ftpClientInfo.getTimeout(), ftpClientInfo.getTimeUnit()); } /** * <br>Description:获取FTPClient,如果线程池为空,则一直等待。 * <br>Author:张智研([email protected]) * <br>Date:2013-7-4 * @return * @throws InterruptedException */ public static FtpClient take() throws InterruptedException { return fqueue.take(); } }
2、FtpClientProxy类
package com.dripstone.ftp; import java.io.IOException; import java.io.InputStream; import java.net.SocketException; import org.apache.commons.net.ftp.FTPClient; /** * <br>Title:FTPClient代理类 * <br>Description:负责FTPClient功能的代理 * <br>Author:张智研([email protected]) * <br>Date:2013-7-4 */ public class FtpClientProxy { private FtpClient ftpClient; public FtpClientProxy() throws InterruptedException, SocketException, IOException { ftpClient = FtpConnectionPooling.poll(); if (!ftpClient.isConnected()) { FtpClientInfo info = FtpConnectionPooling.getFtpClientInfo();// 获取ftpClient信息 ftpClient.connect(info.getFtpIp(), info.getFtpPort());// 连接 ftpClient.login(info.getFtpUserName(), info.getFtpPassword());// 登陆 ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);// 设置为二进制 } } /** * <br>Description:释放ftpClient * <br>Author:张智研([email protected]) * <br>Date:2013-7-4 * @return */ public boolean release() { if (ftpClient == null) return true; boolean b = FtpConnectionPooling.add(ftpClient); if (b) ftpClient = null; return b; } /** * <br>Description:下载文件 * <br>Author:张智研([email protected]) * <br>Date:2013-7-4 * @param fileName * @return * @throws IOException */ public InputStream retrieveFileStream(String remote) throws IOException { return ftpClient.retrieveFileStream(remote); } /** * <br>Description:上传文件 * <br>Author:张智研([email protected]) * <br>Date:2013-7-4 * @param remote * @param local * @return * @throws IOException */ public boolean storeFile(String remote, InputStream local) throws IOException { return ftpClient.storeFile(remote, local); } /** * <br>Description:获取本地端口 * <br>Author:张智研([email protected]) * <br>Date:2013-7-4 * @return */ public int getLocalPort() { return ftpClient.getLocalPort(); } }
3、FtpClient类
package com.dripstone.ftp; import org.apache.commons.net.ftp.FTPClient; public class FtpClient extends FTPClient { public int order; }
4、FtpClientComparator类
package com.dripstone.ftp; import java.util.Comparator; public class FtpClientComparator implements Comparator<FtpClient> { @Override public int compare(FtpClient arg0, FtpClient arg1) { return arg0.order - arg1.order; } }
5、FtpClientInfo类
package com.dripstone.ftp; import java.util.concurrent.TimeUnit; public class FtpClientInfo { private String ftpIp; // ftp的IP地址 private int ftpPort; // ftp的端口 private String ftpUserName; // ftp的用户名 private String ftpPassword; // ftp的密码 private int maxConnects; // 最大连接数 private long timeout; // 超时时间 ,默认60 private TimeUnit timeUnit;// 超时时间单位,默认为秒 public FtpClientInfo() { timeout = 60; timeUnit = TimeUnit.SECONDS; } public String getFtpIp() { return ftpIp; } public void setFtpIp(String ftpIp) { this.ftpIp = ftpIp; } public int getFtpPort() { return ftpPort; } public void setFtpPort(int ftpPort) { this.ftpPort = ftpPort; } public String getFtpUserName() { return ftpUserName; } public void setFtpUserName(String ftpUserName) { this.ftpUserName = ftpUserName; } public String getFtpPassword() { return ftpPassword; } public void setFtpPassword(String ftpPassword) { this.ftpPassword = ftpPassword; } public int getMaxConnects() { return maxConnects; } public void setMaxConnects(int maxConnects) { this.maxConnects = maxConnects; } public long getTimeout() { return timeout; } public void setTimeout(long timeout) { this.timeout = timeout; } public TimeUnit getTimeUnit() { return timeUnit; } public void setTimeUnit(TimeUnit timeUnit) { this.timeUnit = timeUnit; } }
6、测试类FtpConnectionPoolingTest
package com.dripstone.ftp; import java.io.IOException; public class FtpConnectionPoolingTest extends Thread { private static int n = 0; private static int m = 1; public void run() { try { /********************业务代码调用样例*********************/ System.out.println(m++); FtpClientProxy ftpClientProxy = new FtpClientProxy(); String t = "连接" + ++n; System.out.println(t + "连接成功,端口号:" + ftpClientProxy.getLocalPort()); sleep(1000); System.out.println(t + "释放连接"); ftpClientProxy.release();// 释放连接 /***************************************************/ } catch (InterruptedException | IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { /************需要在服务器启动时进行加载**************/ FtpClientInfo ftpClientInfo = new FtpClientInfo(); ftpClientInfo.setFtpIp("192.168.135.85"); ftpClientInfo.setFtpPassword("test"); ftpClientInfo.setFtpPort(21); ftpClientInfo.setFtpUserName("test"); ftpClientInfo.setMaxConnects(20); FtpConnectionPooling.init(ftpClientInfo); /*******************************************/ /*************************************************************/ try { FtpClientProxy ftpClientProxy1 = new FtpClientProxy(); System.out.println("本地端口" + ftpClientProxy1.getLocalPort()); ftpClientProxy1.release(); ftpClientProxy1.release(); FtpClientProxy ftpClientProxy2 = new FtpClientProxy(); System.out.println("本地端口" + ftpClientProxy2.getLocalPort()); ftpClientProxy2.release(); } catch (InterruptedException | IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } /*************************并发测试*******************************/ for (int i = 1; i <= 40; i++) { FtpConnectionPoolingTest test = new FtpConnectionPoolingTest(); test.start(); } } }