教你如何快速实现一个连接池?,不可思议

}

创建对象池


创建好对象工厂之后,ACP 已经知道你需要的对象如何创建了。那么接下来,你需要根据你的实际需要,去创建一个对象池。在 ACP 中,我们通过 GenericObjectPool 以及 GenericObjectPoolConfig 来创建一个对象池。

// 声明一个对象池

private GenericObjectPool sftpConnectPool;

// 设置连接池配置

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();

poolConfig.setEvictionPolicyClassName(“tech.shuyi.javacodechip.acp.SftpEvictionPolicy”);

poolConfig.setBlockWhenExhausted(true);

poolConfig.setJmxEnabled(false);

poolConfig.setMaxWaitMillis(1000 * 10);

poolConfig.setTimeBetweenEvictionRunsMillis(60 * 1000);

poolConfig.setMinEvictableIdleTimeMillis(20 * 1000);

poolConfig.setTestWhileIdle(true);

poolConfig.setTestOnReturn(true);

poolConfig.setTestOnBorrow(true);

poolConfig.setMaxTotal(3);

// 设置抛弃策略

AbandonedConfig abandonedConfig = new AbandonedConfig();

abandonedConfig.setRemoveAbandonedOnMaintenance(true);

abandonedConfig.setRemoveAbandonedOnBorrow(true);

this.sftpConnectPool = new GenericObjectPool<>(sftpConnectFactory, poolConfig, abandonedConfig);

在上面创建 SFTP 连接池的代码中,我们配置了一些线程池的参数以及设置了抛弃策略。抛弃策略是非常重要的,如果没有设置抛弃策略,那么会拿到失效的连接从而导致获取文件失败。抛弃策略是通过 poolConfig.setEvictionPolicyClassName 来设置的,我们这里设置的是 SftpEvictionPolicy 类,其代码内容如下:

@Slf4j

@Component

public class SftpEvictionPolicy implements EvictionPolicy<com.jcraft.jsch.ChannelSftp> {

@Override

public boolean evict(EvictionConfig config, PooledObject<com.jcraft.jsch.ChannelSftp> underTest, int idleCount) {

try {

// 连接失效时进行驱逐

if (!underTest.getObject().isConnected()) {

log.warn(“connect time out, evict the connection. time={}”,System.currentTimeMillis() - underTest.getLastReturnTime());

return true;

}

}catch (Exception e){

return true;

}

return false;

}

}

看到这里,创建线程池的代码就结束了,SftpConnectPool 文件的全部内容如下:

@Slf4j

public class SftpConnectPool {

private GenericObjectPool sftpConnectPool;

public SftpConnectPool(SftpConnectFactory sftpConnectFactory) {

// 设置连接池配置

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();

poolConfig.setEvictionPolicyClassName(“tech.shuyi.javacodechip.acp.SftpEvictionPolicy”);

poolConfig.setBlockWhenExhausted(true);

poolConfig.setJmxEnabled(false);

poolConfig.setMaxWaitMillis(1000 * 10);

poolConfig.setTimeBetweenEvictionRunsMillis(60 * 1000);

poolConfig.setMinEvictableIdleTimeMillis(20 * 1000);

poolConfig.setTestWhileIdle(true);

poolConfig.setTestOnReturn(true);

poolConfig.setTestOnBorrow(true);

poolConfig.setMaxTotal(3);

// 设置抛弃策略

AbandonedConfig abandonedConfig = new AbandonedConfig();

abandonedConfig.setRemoveAbandonedOnMaintenance(true);

abandonedConfig.setRemoveAbandonedOnBorrow(true);

this.sftpConnectPool = new GenericObjectPool<>(sftpConnectFactory, poolConfig, abandonedConfig);

}

public ChannelSftp borrowObject() {

try {

return sftpConnectPool.borrowObject();

} catch (Exception e) {

log.error(“borrowObject error”, e);

return null;

}

}

public void returnObject(ChannelSftp channelSftp) {

if (channelSftp!=null) {

sftpConnectPool.returnObject(channelSftp);

}

}

}

为了方便使用,我还增加了 borrowObject 和 returnObject 方法,但这两个并不是必须的。在这两个方法中,我们分别调用了 GenericObjectPool 类的 borrowObject 方法和 returnObject 方法。这正是 ACP 提供的、使用线程池对象的方法,先借一个对象,之后归还对象。

注:其实在这一步,已经包含了对象池的

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

使用了。但实际使用的时候,我们经常是将对象池的声明与使用放在同一个类中,因此为了讲解方便,这里没有分开。因此下文的使用对象池,本质上是对对象池做进一步封装。

使用对象池


到这里我们的 SFTP 对象池就已经创建完毕了,是不是非常简单呢!但在实际的工作中,我们通常会在这基础上,做一些封装。对于我们这次的 SFTP 连接池来说,我们会对外直接提供下载文件的服务,将 SFTP 对象池进一步封装起来,不需要关心怎么获取文件。

public class SftpFileHelper {

@Autowired

private SftpConnectPool sftpConnectPool;

public void download(String dir, String file, String saveUrl)throws IOException {

ChannelSftp sftp = sftpConnectPool.borrowObject();

log.info(“begin to download file, dir={}, file={}, saveUrl={}”, dir, file, saveUrl);

try {

if (!StringUtils.isEmpty(dir)) {

sftp.cd(dir);

}

File downloadFile = new File(saveUrl);

sftp.get(file, new FileOutputStream(downloadFile));

}catch (Exception e){

log.warn(“下载文件失败”, e);

}finally {

sftpConnectPool.returnObject(sftp);

}

log.info(“file:{} is download successful”, file);

}

}

最后我们写一个测试用例来试一试,是否能正常下载文件。

@RunWith(SpringRunner.class)

@SpringBootTest

@Slf4j

public class SftpFileHelperTest {

@Autowired

private SftpFileHelper sftpFileHelper;

@Test

public void testDownloadFtpFile() throws Exception {

sftpFileHelper.download(“dir”, “fileName”, “fileName”);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值