关于Springboot中JSCH的使用及说明

目录
  • 1. JSCH简介
  • 2. JSCH依赖
  • 3. 使用方法
    • 3.1 连接远程主机
    • 3.2 ChannelExec使用说明
    • 3.3 ChannelSftp使用说明
    • 3.4 ChannelShell使用说明
    • 3.5 完整工具类代码
  • 4. 使用连接池

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连接池

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot 项目使用hutool 工具进行 http 接口调用的处理方法

    目录 写作目的 hutool简单介绍 实践 引用依赖 post get 请求 end 写作目的 在实际的开发过程中一个互联网的项目来说 ,有可能会涉及到调用外部接口的实际业务场景,原生的比如使用httpclient 也能够达到自己想要的结果处理 ,但是其实在实际开发的时候如果没有使用过类似的技术处理的话或多祸首可能会遇见问题所以这里我简单记录一下今天使用到的工具类: hutool 进行接口http 请求调用处理. hutool简单介绍 关于hutool工具包其实本人使用的不多哈 ,这里面其实封装

  • springboot使用Hutool的JschUtil及下载安装步骤

    目录 windows server 2012 R2安装openssh 1.下载 2.将下载的安装包解压至C:/Program Files/目录下 3.安装ssh服务 4.配置ssh服务 5.添加环境系统变量 6.设置开机sshd服务开机自启 本身自带ssh服务的windows(例如windows10) 开启ssh服务 1.客户端安装 2.服务端安装 3.服务端配置 springboot使用 引入hutool 引入 jsch 使用方式 上传 windows server 2012 R2安装open

  • 关于JSCH使用自定义连接池的说明

    目录 1. JSCH使用方法 2. JSCH工具类 3. 创建连接池 4. 改造shellUtil 5. 添加配置 6. 线程安全问题解决 1. JSCH使用方法 jsch使用方法 2. JSCH工具类 JSCH工具类 3. 创建连接池 ConnectionPool.java @Slf4j public class ConnectionPool { private String strictHostKeyChecking; private Integer timeout; /** * ip地址

  • 关于Springboot中JSCH的使用及说明

    目录 1. JSCH简介 2. JSCH依赖 3. 使用方法 3.1 连接远程主机 3.2 ChannelExec使用说明 3.3 ChannelSftp使用说明 3.4 ChannelShell使用说明 3.5 完整工具类代码 4. 使用连接池 1. JSCH简介 JSch 是SSH2的一个纯Java实现.它允许你连接到一个sshd 服务器,使用端口转发,X11转发,文件传输等等. 你可以将它的功能集成到你自己的 程序中.同时该项目也提供一个J2ME版本用来在手机上直连SSHD服务器. 2.

  • 详解SpringBoot中实现依赖注入功能

    今天给大家介绍一下SpringBoot中是如何实现依赖注入的功能. 在以往spring使用中,依赖注入一般都是通过在Spring的配置文件中添加bean方法实现的,相对于这个方式SpringBoot的实现方式就显得非常便捷了.SpringBoot的实现方式基本都是通过注解实现的. 下面来看一下具体案例,这里我编写了三个测试类用于测试依赖注入到底是否可以正确实现. TestBiz接口: package example.biz; public interface TestBiz { public S

  • 在springboot中对kafka进行读写的示例代码

    springboot对kafka的client很好的实现了集成,使用非常方便,本文也实现了一个在springboot中实现操作kafka的demo. 1.POM配置 只需要在dependencies中增加 spring-kafka的配置即可.完整效果如下: <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifa

  • SpringBoot中自定义注解实现控制器访问次数限制实例

    今天给大家介绍一下SpringBoot中如何自定义注解实现控制器访问次数限制. 在Web中最经常发生的就是利用恶性URL访问刷爆服务器之类的攻击,今天我就给大家介绍一下如何利用自定义注解实现这类攻击的防御操作. 其实这类问题一般的解决思路就是:在控制器中加入自定义注解实现访问次数限制的功能. 具体的实现过程看下面的例子: 步骤一:先定义一个注解类,下面看代码事例: package example.controller.limit; import org.springframework.core.

  • 详解springboot中junit回滚

    springboot中使用junit编写单元测试,并且测试结果不影响数据库. pom引入依赖 如果是IDE生成的项目,该包已经默认引入. <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency&g

  • 详解SpringBoot中Session超时原理说明

    一:前言: 最近支付后台登录一段时间后如果没有任何操作,总是需要重新登录才可以继续访问页面,出现这个问题的原因就是session超时,debug代码后发现session的超时时间是1800s.也就是说当1800秒内没有任何操作,session就会出现超时现象.那这个超时时间是如何设置的呢?然后该如何重新设置此超时时间呢?系统又如何判断session超时的呢?接下来就一一进行解答. 二:系统session超时时间如何默认的? 说明:获取session超时时间的方法为"request.getSess

  • SpringBoot中的Thymeleaf用法

    Thymeleaf Thymeleaf是最近SpringBoot推荐支持的模板框架,官网在thymeleaf.org这里. 我们为什么要用Thymeleaf来作为模板引擎呢?官网给了我们一个非常令人信服的解释: Thymeleaf is a modern server-side Java template engine for both web and standalone environments.> 基本写法就像下面这样: <table> <thead> <tr&g

  • 详解springboot中redis的使用和分布式session共享问题

    对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash.轮训.根据权重.随机等.不管对于哪一种负载均衡算法,由于Nginx对不同的请求分发到某一个Tomcat,Tomcat在运行的时候分别是不同的容器里,因此会出现session不同步或者丢失的问题. 实际上实现Session共享的方案很多,其中一种常用的就是使用Tomcat.Jetty等服务器提供的Session共享功能,将Session的内容统一存储在一个数据库(如MySQL)或缓存(如Redis)中. 本文旨在

  • springboot 中文件上传下载实例代码

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. Spring Boot特点 1. 创建独立的Spring应用程序 2. 嵌入的Tomcat,无需部署WAR文件 3. 简化Maven配置 4. 自动配置Spr

  • springboot中使用redis由浅入深解析

    正文 很多时候,我们会在springboot中配置redis,但是就那么几个配置就配好了,没办法知道为什么,这里就详细的讲解一下 这里假设已经成功创建了一个springboot项目. redis连接工厂类 第一步,需要加上springboot的redis jar包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redi

随机推荐