springboot+commons-pool2 连接池访问sftp

直接上代码

pom.xml

        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-pool2artifactId>
            <version>2.11.0version>
        dependency>

application.xml

sftp:
  host: xxx.xxx.xxx.xxx
  userName: xxxxxx
  passWord: xxxxx
  port: 22
  timeout: 30000 # 设置超时时间为30秒
  prvkeyPath: D:/key/xxxx_ssh

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);
        }
    }
}

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();
    }
}

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);
    }
}

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

你可能感兴趣的:(spring,boot,后端,java)