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.55</version>
</dependency>
<!-- commons-pool2 -->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-pool2</artifactId>
  <version>2.6.1</version>
</dependency>

application.yml配置

sftp:
host: server02 # 服务器ip
port: 22 # ssh端口
username: demofile # 用户名
password: demo # 密码
# 连接池参数
pool:
  max-total: 10
  max-idle: 10
  min-idle: 5

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

}

sftp辅助类

package com.example.ftp;

import com.example.exception.ProjectException;
import com.example.util.ByteUtil;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpException;

import java.io.InputStream;

// sftp辅助类
public class SftpHelper {

  private SftpPool pool;

  public SftpHelper(SftpPool pool) {
      this.pool = pool;
  }

  /**
   * 下载文件
   * @param dir 远程目录
   * @param name 远程文件名
   * @return 文件字节数组
   */
  public byte[] download(String dir, String name) {
      ChannelSftp sftp = pool.borrowObject();
      try {
          sftp.cd(dir);
          InputStream in = sftp.get(name);
          return ByteUtil.inputStreamToByteArray(in);
      } catch (SftpException e) {
          throw new ProjectException("sftp下载文件出错", e);
      } finally {
          pool.returnObject(sftp);
      }
  }

  /**
   * 上传文件
   * @param dir 远程目录
   * @param name 远程文件名
   * @param in 输入流
   */
  public void upload(String dir, String name, InputStream in) {
      ChannelSftp sftp = pool.borrowObject();
      try {
          mkdirs(sftp, dir);
          sftp.cd(dir);
          sftp.put(in, name);
      } catch (SftpException e) {
          throw new ProjectException("sftp上传文件出错", e);
      } finally {
          pool.returnObject(sftp);
      }
  }

  /**
   * 删除文件
   * @param dir 远程目录
   * @param name 远程文件名
   */
  public void delete(String dir, String name) {
      ChannelSftp sftp = pool.borrowObject();
      try {
          sftp.cd(dir);
          sftp.rm(name);
      } catch (SftpException e) {
          throw new ProjectException("sftp删除文件出错", e);
      } finally {
          pool.returnObject(sftp);
      }
  }

  /**
   * 递归创建多级目录
   * @param dir 多级目录
   */
  private void mkdirs(ChannelSftp sftp, String dir) {
      String[] folders = dir.split("/");
      try {
          sftp.cd("/");
          for (String folder: folders) {
              if (folder.length()>0) {
                  try {
                      sftp.cd(folder);
                  } catch (Exception e) {
                      sftp.mkdir(folder);
                      sftp.cd(folder);
                  }
              }
          }
      } catch (SftpException e) {
          throw new ProjectException("sftp创建目录出错", e);
      }
  }

}

主配置类

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 SftpHelper sftpHelper(SftpPool sftpPool) {
      return new SftpHelper(sftpPool);
  }

}

使用方法

@Autowired
private SftpHelper sftpHelper;

注入辅助类,直接调用方法即可。

关于springboot2.1.3配置sftp自定义sftp连接池的文章就介绍至此,更多相关springboot自定义sftp连接池内容请搜索编程宝库以前的文章,希望大家多多支持编程宝库

在数据流中有两个常用的类,主要是对二进制的读写进行操作,而且如果用其中一个输出,就必须配套使用里面的输入类才能实现,在读写效率上自然相较于以往其他操作更为有效率。下面我们就来看看DataInputStream和D ...