ftp连接池

ftp连接池

Posted by John Doe on 2021-06-19
Words 786 and Reading Time 4 Minutes
Viewed Times

背景

​ 老系统和其他系统对接采用ftp交互(内外网隔离,通过光闸内外网摆渡交互文件.ak),每次对ftp的操作都是新创建连接消耗较大,于是将ftp池化降低ftp创建的消耗,完成系统优化。

介绍

使用依赖:

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
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>

代码分析

FtpClientFactory

FtpClientFactory 继承 org.apache.commons.pool2 包下的BasePooledObjectFactory抽象类。

重写其抽象方法:

1
2
3
4
5
6
7
8
9
10
11
    /**     
* create创建连接放入连接池
*
*/
public abstract T create() throws Exception;

/**
* Wrap the provided instance with an implementation of PooledObject
* 对实际存储的对象T,使用PooledObject进行包装,以便于ObjectPool管理
*/
public abstract PooledObject<T> wrap(T var1);
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
@Override
public FTPClient create() throws Exception {
FTPClient client = new FTPClient();
boolean hasError = false;
try {
client.setDefaultPort(config.getPort());
client.setConnectTimeout(config.getConnectTimeout());
client.setDataTimeout(config.getDataTimeout());
client.setDefaultTimeout(config.getSocketTimeout());
client.connect(config.getHost(), config.getPort());

long startTime = System.currentTimeMillis();
if (!client.login(config.getUsername(), config.getPassword())) {
hasError = true;
String replyStr = client.getReplyString();
client.logout();
throw new FtpClientCreateException("登录FTP失败!" + replyStr);
}

//检测登录是否成功
if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
hasError = true;
String replyStr = client.getReplyString();
client.disconnect();
throw new FtpClientCreateException("FTP拒绝连接!" + replyStr);

}
client.setFileType(FTP.BINARY_FILE_TYPE);
client.enterLocalPassiveMode();
client.setBufferSize(config.getBufferSize());
logger.info("ftp【{}】链接创建成功,用时:{}毫秒", config.getHost(),
(System.currentTimeMillis() - startTime));
return client;
} finally {
// 如果发生异常,关闭已经创建的连接
if (hasError) {
closeCon(client);
}
}
}

@Override
public PooledObject<FTPClient> wrap(FTPClient ftpClient) {
return new DefaultPooledObject<>(ftpClient);
}

其他方法如下,可根据业务需要修改。

1
2
3
4
5
// 销毁连接
public void destroyObject(PooledObject<FTPClient> p)

// 验证连接(FtpConfig中若开启testonborrow、testonreturn配置后进入该方法校验)
public boolean validateObject(PooledObject<FTPClient> p)

FtpClientPool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class FtpClientPool extends GenericObjectPool<FTPClient> {

public FtpClientPool(PooledObjectFactory<FTPClient> factory) {
super(factory);
}

public FtpClientPool(PooledObjectFactory<FTPClient> factory, GenericObjectPoolConfig config) {
super(factory, config);
}

@Override
public void returnObject(FTPClient obj) {
if (obj != null) {
super.returnObject(obj);
}
}
}

FtpConfig

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
@Data
@Configuration
@ConfigurationProperties(prefix = "ftp")
public class FtpConfig {

/**
* ftp地址
*/
private String host;

/**
* ftp端口
*/
private int port;

/**
* ftp用户名
*/
private String username;

/**
* ftp密码
*/
private String password;

//.......

/**
* 连接池
*
*/
@PostConstruct
public void ftpClientPool() {
// 初始化连接池
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setTestOnBorrow(true);
config.setTestWhileIdle(true);
config.setMaxTotal(this.poolMaxActive);
config.setMaxIdle(this.poolMaxIdle);
config.setMinIdle(this.poolMinIdle);
config.setMaxWaitMillis(this.poolMaxWait);
config.setTimeBetweenEvictionRunsMillis(this.checkIdleTime);
FtpClientPool ftpClientPool = new FtpClientPool(
new FtpClientFactory(this), config);
FtpUtil.initPool(ftpClientPool);

}
}

This is copyright.

...

...

00:00
00:00