关于Springboot中JSCH的使用及说明

作者:喝酸奶要舔盖儿 时间:2023-11-28 02:32:16 

1. JSCH简介

JSch 是SSH2的一个纯Java实现。它允许你连接到一个sshd 服务器,使用端口转发,X11转发,文件传输等等。

你可以将它的功能集成到你自己的 程序中。同时该项目也提供一个J2ME版本用来在手机上直连SSHD服务器。

2. JSCH依赖

        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.55</version>
        </dependency>

3. 使用方法

3.1 连接远程主机

/**
    * 初始化
    *
    * @param ip       远程主机IP地址
    * @param port     远程主机端口
    * @param username 远程主机登陆用户名
    * @param password 远程主机登陆密码
    * @throws JSchException JSch异常
    */
   public void init(String ip, Integer port, String username, String password) throws JSchException {
       JSch jsch = new JSch();
       session = jsch.getSession(username, ip, port);
       session.setPassword(password);
       Properties sshConfig = new Properties();
       sshConfig.put("StrictHostKeyChecking", strictHostKeyChecking);
       session.setConfig(sshConfig);
       session.connect(timeout);
       log.info("Session connected!");
   }
   public void init(String ip, String username, String password) throws JSchException {
       init(ip,22,username,password);
   }

3.2 ChannelExec使用说明

/**
    * 连接多次执行命令,执行命令完毕后需要执行close()方法
    *
    * @param command 需要执行的指令
    * @return 执行结果
    * @throws Exception 没有执行初始化
    */
   public String execCmd(String command) throws Exception {
       // 打开执行shell指令的通道
       channel = session.openChannel("exec");
       channelExec = (ChannelExec) channel;
       if (session == null || channel == null || channelExec == null) {
           log.error("请先执行init()");
           throw new Exception("请先执行init()");
       }
       log.info("execCmd command - > {}", command);
       channelExec.setCommand(command);
       channel.setInputStream(null);
       channelExec.setErrStream(System.err);
       channel.connect();
       StringBuilder sb = new StringBuilder(16);
       try (InputStream in = channelExec.getInputStream();
            InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
            BufferedReader reader = new BufferedReader(isr)) {
           String buffer;
           while ((buffer = reader.readLine()) != null) {
               sb.append("\n").append(buffer);
           }
           log.info("execCmd result - > {}", sb);
           return sb.toString();
       }
   }
   /**
    * 执行命令关闭连接
    * @param command 需要执行的指令
    * @return 执行结果
    * @throws Exception 没有执行初始化
    */
   public String execCmdAndClose(String command) throws Exception {
       String result = execCmd(command);
       close();
       return result;
   }

/**
    * 释放资源
    */
   public void close() {
       if (channelExec != null && channelExec.isConnected()) {
           channelExec.disconnect();
       }
       if (channel != null && channel.isConnected()) {
           channel.disconnect();
       }
       if (session != null && session.isConnected()) {
           session.disconnect();
       }
   }

3.3 ChannelSftp使用说明

3.3.1 ChannelSftp简介

ChannelSftp类是JSch实现SFTP核心类,它包含了所有SFTP的方法,如:

  • put(): 文件上传

  • get(): 文件下载

  • cd(): 进入指定目录

  • ls(): 得到指定目录下的文件列表

  • rename(): 重命名指定文件或目录

  • rm(): 删除指定文件

  • mkdir(): 创建目录

  • rmdir(): 删除目录

3.3.2 JSch支持三种文件传输模式:

模式描述
OVERWRITE完全覆盖模式,这是JSch的默认文件传输模式,即如果目标文件已经存在,传输的文件将完全覆盖目标文件,产生新的文件。
RESUME恢复模式,如果文件已经传输一部分,这时由于网络或其他任何原因导致文件传输中断,如果下一次传输相同的文件,则会从上一次中断的地方续传。
APPEND追加模式,如果目标文件已存在,传输的文件将在目标文件后追加。

3.3.3 文件上传

实现文件上传可以调用ChannelSftp对象的put方法。ChannelSftp中有12个put方法的重载方法:

方法描述
public void put(String src, String dst)将本地文件名为src的文件上传到目标服务器,目标文件名为dst,若dst为目录,则目标文件名将与src文件名相同。采用默认的传输模式:OVERWRITE
public void put(String src, String dst, int mode)将本地文件名为src的文件上传到目标服务器,目标文件名为dst,若dst为目录,则目标文件名将与src文件名相同。指定文件传输模式为mode(mode可选值为:ChannelSftp.OVERWRITE,ChannelSftp.RESUME,ChannelSftp.APPEND)
public void put(String src, String dst, SftpProgressMonitor monitor)将本地文件名为src的文件上传到目标服务器,目标文件名为dst,若dst为目录,则目标文件名将与src文件名相同。采用默认的传输模式:OVERWRITE,并使用实现了SftpProgressMonitor接口的monitor对象来监控文件传输的进度。
public void put(String src, String dst,SftpProgressMonitor monitor, int mode)将本地文件名为src的文件上传到目标服务器,目标文件名为dst,若dst为目录,则目标文件名将与src文件名相同。指定传输模式为mode,并使用实现了SftpProgressMonitor接口的monitor对象来监控文件传输的进度。
public void put(InputStream src, String dst)将本地的input stream对象src上传到目标服务器,目标文件名为dst,dst不能为目录。采用默认的传输模式:OVERWRITE
public void put(InputStream src, String dst, int mode)将本地的input stream对象src上传到目标服务器,目标文件名为dst,dst不能为目录。指定文件传输模式为mode
public void put(InputStream src, String dst, SftpProgressMonitor monitor)将本地的input stream对象src上传到目标服务器,目标文件名为dst,dst不能为目录。采用默认的传输模式:OVERWRITE,并使用实现了SftpProgressMonitor接口的monitor对象来监控传输的进度。
public void put(InputStream src, String dst,SftpProgressMonitor monitor, int mode)将本地的input stream对象src上传到目标服务器,目标文件名为dst,dst不能为目录。指定文件传输模式为mode,并使用实现了SftpProgressMonitor接口的monitor对象来监控传输的进度。
public OutputStream put(String dst)该方法返回一个输出流,可以向该输出流中写入数据,最终将数据传输到目标服务器,目标文件名为dst,dst不能为目录。采用默认的传输模式:OVERWRITE
public OutputStream put(String dst, final int mode)该方法返回一个输出流,可以向该输出流中写入数据,最终将数据传输到目标服务器,目标文件名为dst,dst不能为目录。指定文件传输模式为mode
public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode)该方法返回一个输出流,可以向该输出流中写入数据,最终将数据传输到目标服务器,目标文件名为dst,dst不能为目录。指定文件传输模式为mode,并使用实现了SftpProgressMonitor接口的monitor对象来监控传输的进度。
public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode, long offset)该方法返回一个输出流,可以向该输出流中写入数据,最终将数据传输到目标服务器,目标文件名为dst,dst不能为目录。指定文件传输模式为mode,并使用实现了SftpProgressMonitor接口的monitor对象来监控传输的进度。offset指定了一个偏移量,从输出流偏移offset开始写入数据。

   /**
    * SFTP文件上传
    *
    * @param src 源地址
    * @param dst 目的地址
    * @throws Exception 上传文件失败
    */
   public void putAndClose(String src, String dst) throws Exception {
       putAndClose(src, dst, ChannelSftp.OVERWRITE);
   }
   /**
    * SFTP文件上传
    *
    * @param src  源地址
    * @param dst  目的地址
    * @param mode 上传模式 默认为ChannelSftp.OVERWRITE
    * @throws Exception 上传文件失败
    */
   public void putAndClose(String src, String dst, int mode) throws Exception {
       initChannelSftp();
       log.info("Upload File {} -> {}", src, dst);
       channelSftp.put(src, dst, mode);
       log.info("Upload File Success!");
       close();
   }
   /**
    * SFTP文件上传并监控上传进度
    *
    * @param src 源地址
    * @param dst 目的地址
    * @throws Exception 上传文件失败
    */
   public void putMonitorAndClose(String src, String dst) throws Exception {
       putMonitorAndClose(src, dst, ChannelSftp.OVERWRITE);
   }
   /**
    * SFTP文件上传并监控上传进度
    *
    * @param src  源地址
    * @param dst  目的地址
    * @param mode 上传模式 默认为ChannelSftp.OVERWRITE
    * @throws Exception 上传文件失败
    */
   public void putMonitorAndClose(String src, String dst, int mode) throws Exception {
       initChannelSftp();
       UploadMonitor monitor = new UploadMonitor(new File(src).length());
       log.info("Upload File {} -> {}", src, dst);
       channelSftp.put(src, dst, monitor, mode);
       log.info("Upload File Success!");
       close();
   }
   /**
    * 释放资源
    */
   public void close() {
       if (channelSftp != null && channelSftp.isConnected()) {
           channelSftp.disconnect();
       }
       if (channel != null && channel.isConnected()) {
           channel.disconnect();
       }
       if (session != null && session.isConnected()) {
           session.disconnect();
       }
   }
   private void initChannelSftp() throws Exception {
       channel = session.openChannel("sftp");
       channel.connect(); // 建立SFTP通道的连接
       channelSftp = (ChannelSftp) channel;
       if (session == null || channel == null || channelSftp == null) {
           log.error("请先执行init()");
           throw new Exception("请先执行init()");
       }
   }
}

3.3.4 文件下载

JSch文件下载是通过调用ChannelSftp对象的get方法来实现的。ChannelSftp中有9个get方法的重载方法:

方法描述
publicvoid get(String src, String dst)将目标服务器上文件名为src的文件下载到本地,本地文件名为dst。若dst为目录,则下载到本地的文件名将与src文件名相同。(注:src必须是文件,不能为目录),采用默认的传输模式:OVERWRITE
publicvoid get(String src, String dst, SftpProgressMonitor monitor)将目标服务器上文件名为src的文件下载到本地,本地文件名为dst。若dst为目录,则下载到本地的文件名将与src文件名相同。(注:src必须是文件,不能为目录),采用默认的传输模式:OVERWRITE
publicvoid get(String src, String dst,SftpProgressMonitor monitor, int mode)将目标服务器上文件名为src的文件下载到本地,本地文件名为dst。若dst为目录,则下载到本地的文件名将与src文件名相同。(注:src必须是文件,不能为目录)指定文件传输模式为mode(mode可选值为:ChannelSftp.OVERWRITE,ChannelSftp.RESUME,ChannelSftp.APPEND),并使用实现了SftpProgressMonitor接口的monitor对象来监控文件的传输进度。
publicvoid get(String src, OutputStream dst)将目标服务器上文件名为src的文件下载到本地,下载的数据写入到输出流对象dst(如:文件输出流)。采用默认的传输模式:OVERWRITE
publicvoid get(String src, OutputStream dst, SftpProgressMonitor monitor)将目标服务器上文件名为src的文件下载到本地,下载的数据写入到输出流对象dst(如:文件输出流)。采用默认的传输模式:OVERWRITE,并使用实现了SftpProgressMonitor接口的monitor对象来监控文件的传输进度。
publicvoid get(String src, OutputStream dst, SftpProgressMonitor monitor, int mode, long skip)将目标服务器上文件名为src的文件下载到本地,下载的数据写入到输出流对象dst(如:文件输出流)。指定文件传输模式为mode并使用实现了SftpProgressMonitor接口的monitor对象来监控文件的传输进度。skip指定了一个跳读量,即下载时从src文件跳过skip字节的数据。(一般不推荐使用该参数,默认设为0)
public InputStream get(String src)该方法返回一个输入流,该输入流含有目标服务器上文件名为src的文件数据。可以从该输入流中读取数据,最终将数据传输到本地(如:读取数据后将数据写入到本地的文件中)(注:该方法不支持多种文件传输模式,如何读取与保存数据由应用程序自己确定)
public InputStream get(String src, SftpProgressMonitor monitor)该方法返回一个输入流,该输入流含有目标服务器上文件名为src的文件数据。可以从该输入流中读取数据,最终将数据传输到本地(如:读取数据后将数据写入到本地的文件中)并使用实现了SftpProgressMonitor接口的monitor对象来监控文件的传输进度。(注:该方法不支持多种文件传输模式,如何读取与保存数据由应用程序自己确定)
public InputStream get(String src, final SftpProgressMonitor monitor, finallong skip)该方法返回一个输入流,该输入流含有目标服务器上文件名为src的文件数据。可以从该输入流中读取数据,最终将数据传输到本地(如:读取数据后将数据写入到本地的文件中)并使用实现了SftpProgressMonitor接口的monitor对象来监控文件的传输进度。(注:该方法不支持多种文件传输模式,如何读取与保存数据由应用程序自己确定)skip指定了一个跳读量,即下载时从src文件跳过skip字节的数据。(一般不推荐使用该参数,默认设为0)
/**
    * SFTP文件下载
    *
    * @param src 源文件地址
    * @param dst 目的地址
    * @throws Exception 下载文件失败
    */
   public void getAndClose(String src, String dst) throws Exception {
       initChannelSftp();
       log.info("Download File {} -> {}", src, dst);
       channelSftp.get(src, dst);
       log.info("Download File Success!");
       close();
   }
   public void getMonitorAndClose(String src, String dst) throws Exception {
       initChannelSftp();
       FileProgressMonitor monitor = new FileProgressMonitor(new File(src).length());
       log.info("Download File {} -> {}", src, dst);
       channelSftp.get(src, dst, monitor);
       log.info("Download File Success!");
       close();
   }

3.4 ChannelShell使用说明

3.4.1 shell代码

/**
    * 执行复杂shell命令
    * @param cmds 多条命令
    * @return 执行结果
    * @throws Exception 连接异常
    */
   public String execCmdByShell(String... cmds)throws Exception{
       return execCmdByShell(Arrays.asList(cmds));
   }
/**
    * 执行复杂shell命令
    * @param cmds 多条命令
    * @return 执行结果
    * @throws Exception 连接异常
    */
   public String execCmdByShell(List<String> cmds) throws Exception {
       String result = "";
       initChannelShell();
       InputStream inputStream = channelShell.getInputStream();
       channelShell.setPty(true);
       channelShell.connect();
       OutputStream outputStream = channelShell.getOutputStream();
       PrintWriter printWriter = new PrintWriter(outputStream);
       for (String cmd : cmds) {
           printWriter.println(cmd);
       }
       printWriter.flush();
       byte[] tmp = new byte[1024];
       while (true) {
           while (inputStream.available() > 0) {
               int i = inputStream.read(tmp, 0, 1024);
               if (i < 0) {
                   break;
               }
               String s = new String(tmp, 0, i);
               if (s.contains("--More--")) {
                   outputStream.write((" ").getBytes());
                   outputStream.flush();
               }
               System.out.println(s);
           }
           if (channelShell.isClosed()) {
               System.out.println("exit-status:" + channelShell.getExitStatus());
               break;
           }
           try {
               Thread.sleep(1000);
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
       outputStream.close();
       inputStream.close();
       return result;
   }
private void initChannelShell() throws Exception {
       // 打开执行shell指令的通道
       channel = session.openChannel("shell");
       channelShell = (ChannelShell) channel;
       if (session == null || channel == null || channelShell == null) {
           log.error("请先执行init()");
           throw new Exception("请先执行init()");
       }
   }

3.5 完整工具类代码

ShellUtil.java

@Slf4j
@Component
@Slf4j
@Component
@Scope(value = "prototype")
public class ShellUtil {
   @Value("${ssh.strictHostKeyChecking:no}")
   private String strictHostKeyChecking;
   @Value("${ssh.timeout:30000}")
   private Integer timeout;
   private Session session;
   private Channel channel;
   private ChannelExec channelExec;
   private ChannelSftp channelSftp;
   private ChannelShell channelShell;
   /**
    * 初始化
    *
    * @param ip       远程主机IP地址
    * @param port     远程主机端口
    * @param username 远程主机登陆用户名
    * @param password 远程主机登陆密码
    * @throws JSchException JSch异常
    */
   public void init(String ip, Integer port, String username, String password) throws JSchException {
       JSch jsch = new JSch();
       session = jsch.getSession(username, ip, port);
       session.setPassword(password);
       Properties sshConfig = new Properties();
       sshConfig.put("StrictHostKeyChecking", strictHostKeyChecking);
       session.setConfig(sshConfig);
       session.connect(timeout);
       log.info("Session connected!");
   }
   public void init(String ip, String username, String password) throws JSchException {
       init(ip, 22, username, password);
   }
   /**
    * 连接多次执行命令,执行命令完毕后需要执行close()方法
    *
    * @param command 需要执行的指令
    * @return 执行结果
    * @throws Exception 没有执行初始化
    */
   public String execCmd(String command) throws Exception {
       initChannelExec();
       log.info("execCmd command - > {}", command);
       channelExec.setCommand(command);
       channel.setInputStream(null);
       channelExec.setErrStream(System.err);
       channel.connect();
       StringBuilder sb = new StringBuilder(16);
       try (InputStream in = channelExec.getInputStream();
            InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
            BufferedReader reader = new BufferedReader(isr)) {
           String buffer;
           while ((buffer = reader.readLine()) != null) {
               sb.append("\n").append(buffer);
           }
           log.info("execCmd result - > {}", sb);
           return sb.toString();
       }
   }
   /**
    * 执行命令关闭连接
    *
    * @param command 需要执行的指令
    * @return 执行结果
    * @throws Exception 没有执行初始化
    */
   public String execCmdAndClose(String command) throws Exception {
       String result = execCmd(command);
       close();
       return result;
   }
   /**
    * 执行复杂shell命令
    *
    * @param cmds 多条命令
    * @return 执行结果
    * @throws Exception 连接异常
    */
   public String execCmdByShell(String... cmds) throws Exception {
       return execCmdByShell(Arrays.asList(cmds));
   }
   /**
    * 执行复杂shell命令
    *
    * @param cmds 多条命令
    * @return 执行结果
    * @throws Exception 连接异常
    */
   public String execCmdByShell(List<String> cmds) throws Exception {
       String result = "";
       initChannelShell();
       InputStream inputStream = channelShell.getInputStream();
       channelShell.setPty(true);
       channelShell.connect();
       OutputStream outputStream = channelShell.getOutputStream();
       PrintWriter printWriter = new PrintWriter(outputStream);
       for (String cmd : cmds) {
           printWriter.println(cmd);
       }
       printWriter.flush();
       byte[] tmp = new byte[1024];
       while (true) {
           while (inputStream.available() > 0) {
               int i = inputStream.read(tmp, 0, 1024);
               if (i < 0) {
                   break;
               }
               String s = new String(tmp, 0, i);
               if (s.contains("--More--")) {
                   outputStream.write((" ").getBytes());
                   outputStream.flush();
               }
               System.out.println(s);
           }
           if (channelShell.isClosed()) {
               System.out.println("exit-status:" + channelShell.getExitStatus());
               break;
           }
           try {
               Thread.sleep(1000);
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
       outputStream.close();
       inputStream.close();
       return result;
   }
   /**
    * SFTP文件上传
    *
    * @param src 源地址
    * @param dst 目的地址
    * @throws Exception 上传文件失败
    */
   public void putAndClose(String src, String dst) throws Exception {
       putAndClose(src, dst, ChannelSftp.OVERWRITE);
   }
   /**
    * SFTP文件上传
    *
    * @param src  源地址
    * @param dst  目的地址
    * @param mode 上传模式 默认为ChannelSftp.OVERWRITE
    * @throws Exception 上传文件失败
    */
   public void putAndClose(String src, String dst, int mode) throws Exception {
       put(src, dst, mode);
       close();
   }
   public void put(String src, String dst) throws Exception {
       put(src, dst, ChannelSftp.OVERWRITE);
   }
   public void put(String src, String dst, int mode) throws Exception {
       initChannelSftp();
       log.info("Upload File {} -> {}", src, dst);
       channelSftp.put(src, dst, mode);
       log.info("Upload File Success!");
   }
   /**
    * SFTP文件上传并监控上传进度
    *
    * @param src 源地址
    * @param dst 目的地址
    * @throws Exception 上传文件失败
    */
   public void putMonitorAndClose(String src, String dst) throws Exception {
       putMonitorAndClose(src, dst, ChannelSftp.OVERWRITE);
   }
   /**
    * SFTP文件上传并监控上传进度
    *
    * @param src  源地址
    * @param dst  目的地址
    * @param mode 上传模式 默认为ChannelSftp.OVERWRITE
    * @throws Exception 上传文件失败
    */
   public void putMonitorAndClose(String src, String dst, int mode) throws Exception {
       initChannelSftp();
       FileProgressMonitor monitor = new FileProgressMonitor(new File(src).length());
       log.info("Upload File {} -> {}", src, dst);
       channelSftp.put(src, dst, monitor, mode);
       log.info("Upload File Success!");
       close();
   }
   /**
    * SFTP文件下载
    *
    * @param src 源文件地址
    * @param dst 目的地址
    * @throws Exception 下载文件失败
    */
   public void getAndClose(String src, String dst) throws Exception {
       get(src,dst);
       close();
   }
   public void get(String src, String dst) throws Exception {
       initChannelSftp();
       log.info("Download File {} -> {}", src, dst);
       channelSftp.get(src, dst);
       log.info("Download File Success!");
   }
   /**
    * SFTP文件下载并监控下载进度
    *
    * @param src 源文件地址
    * @param dst 目的地址
    * @throws Exception 下载文件失败
    */
   public void getMonitorAndClose(String src, String dst) throws Exception {
       initChannelSftp();
       FileProgressMonitor monitor = new FileProgressMonitor(new File(src).length());
       log.info("Download File {} -> {}", src, dst);
       channelSftp.get(src, dst, monitor);
       log.info("Download File Success!");
       close();
   }
   /**
    * 删除指定目录文件
    *
    * @param path 删除路径
    * @throws Exception 远程主机连接异常
    */
   public void deleteFile(String path) throws Exception {
       initChannelSftp();
       channelSftp.rm(path);
       log.info("Delete File {}", path);
   }
   /**
    * 删除指定目录
    *
    * @param path 删除路径
    * @throws Exception 远程主机连接异常
    */
   public void deleteDir(String path) throws Exception {
       initChannelSftp();
       channelSftp.rmdir(path);
       log.info("Delete Dir {} ", path);
   }
   /**
    * 释放资源
    */
   public void close() {
       if (channelSftp != null && channelSftp.isConnected()) {
           channelSftp.disconnect();
       }
       if (channelExec != null && channelExec.isConnected()) {
           channelExec.disconnect();
       }
       if (channel != null && channel.isConnected()) {
           channel.disconnect();
       }
       if (session != null && session.isConnected()) {
           session.disconnect();
       }
   }
   private void initChannelSftp() throws Exception {
       channel = session.openChannel("sftp");
       channel.connect(); // 建立SFTP通道的连接
       channelSftp = (ChannelSftp) channel;
       if (session == null || channel == null || channelSftp == null) {
           log.error("请先执行init()");
           throw new Exception("请先执行init()");
       }
   }
   private void initChannelExec() throws Exception {
       // 打开执行shell指令的通道
       channel = session.openChannel("exec");
       channelExec = (ChannelExec) channel;
       if (session == null || channel == null || channelExec == null) {
           log.error("请先执行init()");
           throw new Exception("请先执行init()");
       }
   }
   private void initChannelShell() throws Exception {
       // 打开执行shell指令的通道
       channel = session.openChannel("shell");
       channelShell = (ChannelShell) channel;
       if (session == null || channel == null || channelShell == null) {
           log.error("请先执行init()");
           throw new Exception("请先执行init()");
       }
   }
}

FileProgressMonitor.java

@Slf4j
public class FileProgressMonitor extends TimerTask implements SftpProgressMonitor {
   private boolean isEnd = false;
   private long transfered;
   private long fileSize;
   private ScheduledExecutorService executorService;
   private boolean isScheduled = false;
   long startTime = 0L;
   public FileProgressMonitor(long fileSize) {
       this.fileSize = fileSize;
   }
   @Override
   public void run() {
       if (!isEnd()) {
           log.info("Transfering is in progress.");
           long transfered = getTransfered();
           // 判断当前已传输数据大小是否等于文件总大小
           if (transfered != fileSize) {
               log.info("Current transfered: {} bytes", transfered);
               sendProgressMessage(transfered);
           } else {
               // 如果当前已传输数据大小等于文件总大小,说明已完成,设置end
               log.info("File transfering is done.");
               setEnd(true);
           }
       } else {
           log.info("Transfering done. Cancel timer.");
           // 如果传输结束,停止timer记时器
           stop();
           return;
       }
   }
   /**
    * 实现了SftpProgressMonitor接口的count方法
    */
   @Override
   public boolean count(long count) {
       if (isEnd()) {
           return false;
       }
       if (!isScheduled) {
           start();
       }
       add(count);
       return true;
   }
   /**
    * 实现了SftpProgressMonitor接口的end方法
    */
   @Override
   public void end() {
       setEnd(true);
       log.info("transfering end. time ->{} s", (System.currentTimeMillis() - startTime) / 1000);
   }
   @Override
   public void init(int op, String src, String dest, long max) {
       startTime = System.currentTimeMillis();
   }
   public void stop() {
       log.info("Try to stop progress monitor.");
       boolean isShutdown = executorService.isShutdown();
       if (!isShutdown) {
           executorService.shutdown();
       }
       log.info("Progress monitor stoped.");
   }
   public void start() {
       log.info("Try to start progress monitor.");
       executorService = new ScheduledThreadPoolExecutor(1);
       //1秒钟后开始执行,每2杪钟执行一次
       executorService.scheduleWithFixedDelay(this, 1, 1, TimeUnit.SECONDS);
       isScheduled = true;
       log.info("Progress monitor started.");
   }
   /**
    * 打印progress信息
    *
    * @param transfered
    */
   private void sendProgressMessage(long transfered) {
       if (fileSize != 0) {
           double d = ((double) transfered * 100) / (double) fileSize;
           DecimalFormat df = new DecimalFormat("#.##");
           log.info("Sending progress message: {} %", df.format(d));
       } else {
           log.info("Sending progress message: {}", transfered);
       }
   }
   private synchronized void add(long count) {
       transfered = transfered + count;
   }
   private synchronized long getTransfered() {
       return transfered;
   }
   public synchronized void setTransfered(long transfered) {
       this.transfered = transfered;
   }
   private synchronized void setEnd(boolean isEnd) {
       this.isEnd = isEnd;
   }
   private synchronized boolean isEnd() {
       return isEnd;
   }
}

4. 使用连接池

jsch连接池

来源:https://blog.csdn.net/qq_39361915/article/details/112762028

标签:Springboot,JSCH
0
投稿

猜你喜欢

  • Java异常学习之自定义异常详解

    2023-09-25 00:57:27
  • Android Studio使用小技巧:布局预览时填充数据

    2021-06-04 09:00:03
  • Java HashMap三种循环遍历方式及其性能对比实例分析

    2022-03-22 18:36:45
  • Java启用Azure Linux虚拟机诊断设置

    2022-06-28 05:42:51
  • Android多个TAB选项卡切换效果

    2022-04-10 03:03:15
  • Android编程实现3D立体旋转效果的实例代码

    2023-04-01 13:40:50
  • Spring Security实现用户名密码登录详解

    2021-05-24 14:32:36
  • idea +junit单元测试获取不到bean注入的解决方式

    2022-12-09 05:59:27
  • Android编程之蓝牙测试实例

    2022-06-09 13:59:53
  • Java获取文件的类型和扩展名的实现方法

    2021-09-24 08:56:56
  • 解析C#拼接Json串的几种方法

    2021-12-28 20:22:48
  • Java CPU性能分析工具代码实例

    2023-09-28 04:52:54
  • spring boot 日志配置详解

    2023-09-24 00:23:11
  • Android 双击返回键退出程序的方法总结

    2023-12-05 16:41:18
  • WPF如何自定义TabControl控件样式示例详解

    2021-09-22 07:27:34
  • 深入解析C#中的泛型类与泛型接口

    2023-04-30 02:35:39
  • Java螺旋矩阵处理方法详解

    2021-09-24 02:14:55
  • C#指针变量与unsafe的实现

    2022-09-05 09:34:10
  • idea 如何查找类中的某个方法

    2022-03-17 17:17:42
  • json格式数据分析工具PageElement类分享(仿Session写法)

    2023-09-16 16:04:32
  • asp之家 软件编程 m.aspxhome.com