• springboot+commons-pool2 连接池访问sftp


    直接上代码

    pom.xml

            <dependency>
                <groupId>org.apache.commonsgroupId>
                <artifactId>commons-pool2artifactId>
                <version>2.11.0version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    application.xml

    sftp:
      host: xxx.xxx.xxx.xxx
      userName: xxxxxx
      passWord: xxxxx
      port: 22
      timeout: 30000 # 设置超时时间为30秒
      prvkeyPath: D:/key/xxxx_ssh
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    SftpConfig.java

    @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)这个注解很重要, 代码重构后启动报错MXBean already registered with name org.apache.commons.pool2:type=GenericObj,加上这个注解后异常消失.

    @Configuration
    @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
    public class SftpConfig {
    
        @Value("${sftp.host}")
        private String sftpHost;
    
        @Value("${sftp.userName}")
        private String sftpUserName;
    
        @Value("${sftp.passWord}")
        private String sftpPassWord;
    
        @Value("${sftp.port}")
        private int sftpPort;
    
        @Value("${sftp.timeout}")
        private int sftpTimeout;
    
        @Value("${sftp.prvkeyPath}")
        private String prvkeyPath;
    
        @Bean
        public JSch jsch() {
            return new JSch();
        }
    
        @Bean
        public Session jschSession(JSch jsch) throws JSchException {
            Session session = jsch.getSession(sftpUserName, sftpHost, sftpPort);
            session.setConfig("StrictHostKeyChecking", "no");
            session.setTimeout(sftpTimeout);
            session.setPassword(""); // 不使用密码,使用密钥认证
            jsch.addIdentity(prvkeyPath, sftpPassWord); // 添加私钥文件
            return session;
        }
    
        @Bean
        public GenericObjectPoolConfig<ChannelSftp> sftpPoolConfig() {
            GenericObjectPoolConfig<ChannelSftp> poolConfig = new GenericObjectPoolConfig<>();
            poolConfig.setMaxTotal(10); // 最大连接数
            poolConfig.setMaxIdle(5);   // 最大空闲连接数
            poolConfig.setMinIdle(1);   // 最小空闲连接数
            poolConfig.setMaxWait(Duration.ofMillis(10000)); // 最长等待时间(Duration对象)
            // 其他连接池配置参数...
            return poolConfig;
        }
    
        @Bean
        public GenericObjectPool<ChannelSftp> sftpChannelPool(Session jschSession) {
            GenericObjectPool<ChannelSftp> pool = new GenericObjectPool<>(new ChannelSftpFactory(jschSession));
            return pool;
        }
    
        private static class ChannelSftpFactory extends BasePooledObjectFactory<ChannelSftp> {
            private final Session session;
    
            public ChannelSftpFactory(Session session) {
                this.session = session;
            }
    
            @Override
            public ChannelSftp create() throws Exception {
                if (!session.isConnected()) {
                    session.connect();
                }
                ChannelSftp sftp = (ChannelSftp) session.openChannel("sftp");
                sftp.connect();
                return sftp;
            }
    
            @Override
            public PooledObject<ChannelSftp> wrap(ChannelSftp sftp) {
                return new DefaultPooledObject<>(sftp);
            }
        }
    }
    
    • 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
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    SftpService.java

    @Slf4j
    @Component
    public class SftpService{
    	@Autowired
        private GenericObjectPool<ChannelSftp> sftpChannelPool;
    	
    	public List<String> listFiles(String directory) {
            ChannelSftp sftp = null;
            try {
                sftp = sftpChannelPool.borrowObject();
                Vector files = sftp.ls(directory);
                if (CollUtil.isNotEmpty(files)) {
                    List<String> list = new ArrayList<>(files.size());
                    for (Object object : files) {
                        ChannelSftp.LsEntry file = (ChannelSftp.LsEntry) object;
                        log.info("fileName:{}", file.getFilename());
                        // 文件名需包含后缀名以及排除   .和 ..
                        // boolean match = file.getFilename().contains(matchRule); // 取消文件名称匹配
                        if (!DOT.equals(file.getFilename()) && !DOUBLE_DOT.equals(file.getFilename())
                                && file.getFilename().contains(DOT)) {
                            String newFilePath = directory.endsWith(SLASH) ? directory + file.getFilename() :
                                    directory + SLASH + file.getFilename();
                            list.add(newFilePath);
                        }
                    }
                    return list;
                }
            } catch (Exception e) {
                log.error("sftp list files error", e);
                throw new FileSyncException("sftp list files error");
            }finally {
                if (sftp != null) {
                    try {
                        // 手动归还连接到连接池
                        sftpChannelPool.returnObject(sftp);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            return Collections.emptyList();
        }
    }
    
    
    • 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

    TestController.Java 测试

    @RestController
    @RequestMapping("/sftp")
    public class TestController {
        @Autowired
        private SftpClient sftpClient;
    
        @GetMapping("/listFiles")
        public List<String> listFiles(@RequestParam String directory) {
            return sftpClient.listFiles(directory);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    以上仅提供参考, 代码还有很大优化空间.

  • 相关阅读:
    QT信号和槽的关联实现子窗口传递值给主窗口
    (框架)Deepracer 自动训练 框架的搭建
    计设大赛作品分享
    线程的创建和两种线程实现方式的区别
    图书管理系统的分析与设计
    声音信号处理笔记(一)
    【pandas小技巧】--DataFrame的显示样式
    疫苗预约系统毕业设计,疫苗预约系统设计源码,疫苗预约系统开题报告需求分析
    php 实现:给图片加文字水印,图片水印,压缩图片
    用Python写了一个水果忍者小游戏
  • 原文地址:https://blog.csdn.net/lk1985021/article/details/133131822