原文: https://blog.csdn.net/qq_35433926/article/details/91880345
springboot2.1.3配置sftp,自定义sftp连接池
项目地址
项目地址:https://gitee.com/xuelingkang/spring-boot-demo
完整配置参考com.example.ftp包
maven:
<!-- sftp --> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.56</version> </dependency> <!-- commons-pool2 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.11.1</version> </dependency>
commons-pool2 配置详解: https://www.jianshu.com/p/e9194bd84e38
application.yml配置
sftp: host: server02 # 服务器ip port: 22 # ssh端口 username: demofile # 用户名 password: demo # 密码 # 连接池参数 pool: max-total: 10 max-idle: 10 min-idle: 5
or application.properties
sftp.username = root sftp.password = root sftp.host = 192.168.80.51 sftp.port = 2222 sftp.pool.max-total = 10 sftp.pool.max-idle = 10 sftp.pool.min-idle = 3
sftp.poll.maxWaitMillis = 60000
SftpProperties
package com.example.ftp; import com.jcraft.jsch.ChannelSftp; import lombok.Data; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.boot.context.properties.ConfigurationProperties; @Data @ConfigurationProperties(prefix = "sftp") public class SftpProperties { private String host; private int port = 22; private String username = "root"; private String password = "root"; private Pool pool = new Pool(); public static class Pool extends GenericObjectPoolConfig<ChannelSftp> { private int maxTotal = DEFAULT_MAX_TOTAL; private int maxIdle = DEFAULT_MAX_IDLE; private int minIdle = DEFAULT_MIN_IDLE; public Pool() { super(); } @Override public int getMaxTotal() { return maxTotal; } @Override public void setMaxTotal(int maxTotal) { this.maxTotal = maxTotal; } @Override public int getMaxIdle() { return maxIdle; } @Override public void setMaxIdle(int maxIdle) { this.maxIdle = maxIdle; } @Override public int getMinIdle() { return minIdle; } @Override public void setMinIdle(int minIdle) { this.minIdle = minIdle; } } }
sftp连接工厂
package com.example.ftp; import com.example.exception.ProjectException; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.pool2.BasePooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; import java.util.Properties; @Data @Slf4j public class SftpFactory extends BasePooledObjectFactory<ChannelSftp> { private SftpProperties properties; public SftpFactory(SftpProperties properties) { this.properties = properties; } @Override public ChannelSftp create() { try { JSch jsch = new JSch(); Session sshSession = jsch.getSession(properties.getUsername(), properties.getHost(), properties.getPort()); sshSession.setPassword(properties.getPassword()); Properties sshConfig = new Properties(); sshConfig.put("StrictHostKeyChecking", "no"); sshSession.setConfig(sshConfig); sshSession.connect(); ChannelSftp channel = (ChannelSftp) sshSession.openChannel("sftp"); channel.connect(); return channel; } catch (JSchException e) { throw new ProjectException("连接sfpt失败", e); } } @Override public PooledObject<ChannelSftp> wrap(ChannelSftp channelSftp) { return new DefaultPooledObject<>(channelSftp); } // 销毁对象 @Override public void destroyObject(PooledObject<ChannelSftp> p) { ChannelSftp channelSftp = p.getObject(); channelSftp.disconnect(); } }
sftp连接池
package com.example.ftp; import com.example.exception.ProjectException; import com.jcraft.jsch.ChannelSftp; import lombok.Data; import org.apache.commons.pool2.impl.GenericObjectPool; @Data public class SftpPool { private GenericObjectPool<ChannelSftp> pool; public SftpPool(SftpFactory factory) { this.pool = new GenericObjectPool<>(factory, factory.getProperties().getPool()); } /** * 获取一个sftp连接对象 * @return sftp连接对象 */ public ChannelSftp borrowObject() { try { return pool.borrowObject(); } catch (Exception e) { throw new ProjectException("获取ftp连接失败", e); } } /** * 归还一个sftp连接对象 * @param channelSftp sftp连接对象 */ public void returnObject(ChannelSftp channelSftp) { if (channelSftp!=null) { pool.returnObject(channelSftp); } } }
sftptemplate 辅助类
import com.icil.bx.common.config.SftpPool; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.SftpException; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Vector; /** * @PACKAGE : com.icil.bx.common.utils * @Author : Sea * @Date : 8/23/21 9:31 AM * @Desc : **/ public class SFTPTemplate { private transient Logger log = LoggerFactory.getLogger(this.getClass()); //结合springboot private SftpPool pool; public SFTPTemplate(SftpPool pool) { this.pool = pool; } /** * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory * @param basePath 服务器的基础路径 eg: /upload * @param directory 上传到该目录 eg: img/ or img/cc/ 一定要带上最后的URL,否则返回的url无效 * @param sftpFileName sftp端文件名 eg : xx.png * @param input 输入流 */ public String upload(String basePath,String directory, String sftpFileName, InputStream input) throws Exception { ChannelSftp sftp = pool.borrowObject(); try{ log.info("start upload file {}",sftpFileName); mkdir(basePath,directory,sftp); sftp.put(input, sftpFileName); //上传文件 log.info("end upload file {}",sftpFileName); } catch (Exception e) { throw new Exception(e.getMessage()); }finally { pool.returnObject(sftp); } return directory+sftpFileName; } private void mkdir(String basePath,String directory,ChannelSftp sftp) throws SftpException { try { sftp.cd(basePath); sftp.cd(directory); } catch (SftpException e) { log.info("目录不存在,创建文件夹"); //目录不存在,则创建文件夹 String [] dirs=directory.split("/"); String tempPath=basePath; for(String dir:dirs) { if(null== dir || "".equals(dir)) continue; tempPath+="/"+dir; try{ sftp.cd(tempPath); }catch(SftpException ex){ sftp.mkdir(tempPath); sftp.cd(tempPath); } } } } /** * 下载文件。 * @param directory 下载目录 * @param downloadFile 下载的文件 * @param saveFile 存在本地的路径 */ public void download(String directory, String downloadFile, String saveFile) throws Exception{ ChannelSftp sftp = pool.borrowObject(); try{ if (directory != null && !"".equals(directory)) { sftp.cd(directory); } File file = new File(saveFile); sftp.get(downloadFile, new FileOutputStream(file)); } catch (Exception e) { throw new Exception(e.getMessage()); } finally { pool.returnObject(sftp); } } /** * 下载文件 * @param directory 下载目录 * @param downloadFile 下载的文件名 * @return 字节数组 */ public byte[] download(String directory, String downloadFile) throws Exception{ ChannelSftp sftp = pool.borrowObject(); try { if (directory != null && !"".equals(directory)) { sftp.cd(directory); } InputStream is = sftp.get(downloadFile); return IOUtils.toByteArray(is); } catch (Exception e) { throw new Exception(e.getMessage()); }finally { pool.returnObject(sftp); } } /** * 删除文件 * @param directory 要删除文件所在目录 * @param deleteFile 要删除的文件 */ public void delete(String directory, String deleteFile) throws Exception{ ChannelSftp sftp = pool.borrowObject(); try { sftp.cd(directory); sftp.rm(deleteFile); } catch (Exception e) { throw new Exception(e.getMessage()); }finally { pool.returnObject(sftp); } } /** * 列出目录下的文件 * @param directory 要列出的目录 */ public Vector<?> listFiles(String directory) throws Exception { ChannelSftp sftp = pool.borrowObject(); try { return sftp.ls(directory); } catch (Exception e) { throw new Exception(e.getMessage()); }finally { pool.returnObject(sftp); } } }
主配置类
package com.example.config; import com.example.ftp.SftpFactory; import com.example.ftp.SftpHelper; import com.example.ftp.SftpPool; import com.example.ftp.SftpProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; // ftp配置 @Configuration @EnableConfigurationProperties(SftpProperties.class) public class SftpConfig { // 工厂 @Bean public SftpFactory sftpFactory(SftpProperties properties) { return new SftpFactory(properties); } // 连接池 @Bean public SftpPool sftpPool(SftpFactory sftpFactory) { return new SftpPool(sftpFactory); } // 辅助类
@Bean
public SFTPTemplate sftpTemplate(SftpPool sftpPool) {
return new SFTPTemplate(sftpPool);
}
}
使用方法
@Autowired
private SftpTemplate sftpTemplate;
注入辅助类,直接调用方法即可。