欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于Springboot中JSCH的使用及說明

 更新時間:2022年09月29日 11:13:41   作者:喝酸奶要舔蓋兒  
這篇文章主要介紹了關(guān)于Springboot中JSCH的使用及說明,具有很好的參考價值,希望對大家有所幫助。

1. JSCH簡介

JSch 是SSH2的一個純Java實現(xiàn)。它允許你連接到一個sshd 服務(wù)器,使用端口轉(zhuǎn)發(fā),X11轉(zhuǎn)發(fā),文件傳輸?shù)鹊取?/p>

你可以將它的功能集成到你自己的 程序中。同時該項目也提供一個J2ME版本用來在手機上直連SSHD服務(wù)器。

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使用說明

/**
     * 連接多次執(zhí)行命令,執(zhí)行命令完畢后需要執(zhí)行close()方法
     *
     * @param command 需要執(zhí)行的指令
     * @return 執(zhí)行結(jié)果
     * @throws Exception 沒有執(zhí)行初始化
     */
    public String execCmd(String command) throws Exception {
        // 打開執(zhí)行shell指令的通道
        channel = session.openChannel("exec");
        channelExec = (ChannelExec) channel;
        if (session == null || channel == null || channelExec == null) {
            log.error("請先執(zhí)行init()");
            throw new Exception("請先執(zhí)行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();
        }
    }
    /**
     * 執(zhí)行命令關(guān)閉連接
     * @param command 需要執(zhí)行的指令
     * @return 執(zhí)行結(jié)果
     * @throws Exception 沒有執(zhí)行初始化
     */
    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實現(xiàn)SFTP核心類,它包含了所有SFTP的方法,如:

  • put(): 文件上傳
  • get(): 文件下載
  • cd(): 進入指定目錄
  • ls(): 得到指定目錄下的文件列表
  • rename(): 重命名指定文件或目錄
  • rm(): 刪除指定文件
  • mkdir(): 創(chuàng)建目錄
  • rmdir(): 刪除目錄

3.3.2 JSch支持三種文件傳輸模式:

模式描述
OVERWRITE完全覆蓋模式,這是JSch的默認文件傳輸模式,即如果目標文件已經(jīng)存在,傳輸?shù)奈募⑼耆采w目標文件,產(chǎn)生新的文件。
RESUME恢復模式,如果文件已經(jīng)傳輸一部分,這時由于網(wǎng)絡(luò)或其他任何原因?qū)е挛募鬏斨袛?,如果下一次傳輸相同的文件,則會從上一次中斷的地方續(xù)傳。
APPEND追加模式,如果目標文件已存在,傳輸?shù)奈募⒃谀繕宋募笞芳印?/td>

3.3.3 文件上傳

實現(xiàn)文件上傳可以調(diào)用ChannelSftp對象的put方法。ChannelSftp中有12個put方法的重載方法:

方法描述
public void put(String src, String dst)將本地文件名為src的文件上傳到目標服務(wù)器,目標文件名為dst,若dst為目錄,則目標文件名將與src文件名相同。采用默認的傳輸模式:OVERWRITE
public void put(String src, String dst, int mode)將本地文件名為src的文件上傳到目標服務(wù)器,目標文件名為dst,若dst為目錄,則目標文件名將與src文件名相同。指定文件傳輸模式為mode(mode可選值為:ChannelSftp.OVERWRITE,ChannelSftp.RESUME,ChannelSftp.APPEND)
public void put(String src, String dst, SftpProgressMonitor monitor)將本地文件名為src的文件上傳到目標服務(wù)器,目標文件名為dst,若dst為目錄,則目標文件名將與src文件名相同。采用默認的傳輸模式:OVERWRITE,并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控文件傳輸?shù)倪M度。
public void put(String src, String dst,SftpProgressMonitor monitor, int mode)將本地文件名為src的文件上傳到目標服務(wù)器,目標文件名為dst,若dst為目錄,則目標文件名將與src文件名相同。指定傳輸模式為mode,并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控文件傳輸?shù)倪M度。
public void put(InputStream src, String dst)將本地的input stream對象src上傳到目標服務(wù)器,目標文件名為dst,dst不能為目錄。采用默認的傳輸模式:OVERWRITE
public void put(InputStream src, String dst, int mode)將本地的input stream對象src上傳到目標服務(wù)器,目標文件名為dst,dst不能為目錄。指定文件傳輸模式為mode
public void put(InputStream src, String dst, SftpProgressMonitor monitor)將本地的input stream對象src上傳到目標服務(wù)器,目標文件名為dst,dst不能為目錄。采用默認的傳輸模式:OVERWRITE,并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控傳輸?shù)倪M度。
public void put(InputStream src, String dst,SftpProgressMonitor monitor, int mode)將本地的input stream對象src上傳到目標服務(wù)器,目標文件名為dst,dst不能為目錄。指定文件傳輸模式為mode,并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控傳輸?shù)倪M度。
public OutputStream put(String dst)該方法返回一個輸出流,可以向該輸出流中寫入數(shù)據(jù),最終將數(shù)據(jù)傳輸?shù)侥繕朔?wù)器,目標文件名為dst,dst不能為目錄。采用默認的傳輸模式:OVERWRITE
public OutputStream put(String dst, final int mode)該方法返回一個輸出流,可以向該輸出流中寫入數(shù)據(jù),最終將數(shù)據(jù)傳輸?shù)侥繕朔?wù)器,目標文件名為dst,dst不能為目錄。指定文件傳輸模式為mode
public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode)該方法返回一個輸出流,可以向該輸出流中寫入數(shù)據(jù),最終將數(shù)據(jù)傳輸?shù)侥繕朔?wù)器,目標文件名為dst,dst不能為目錄。指定文件傳輸模式為mode,并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控傳輸?shù)倪M度。
public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode, long offset)該方法返回一個輸出流,可以向該輸出流中寫入數(shù)據(jù),最終將數(shù)據(jù)傳輸?shù)侥繕朔?wù)器,目標文件名為dst,dst不能為目錄。指定文件傳輸模式為mode,并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控傳輸?shù)倪M度。offset指定了一個偏移量,從輸出流偏移offset開始寫入數(shù)據(jù)。
    /**
     * 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文件上傳并監(jiān)控上傳進度
     *
     * @param src 源地址
     * @param dst 目的地址
     * @throws Exception 上傳文件失敗
     */
    public void putMonitorAndClose(String src, String dst) throws Exception {
        putMonitorAndClose(src, dst, ChannelSftp.OVERWRITE);
    }
    /**
     * SFTP文件上傳并監(jiān)控上傳進度
     *
     * @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("請先執(zhí)行init()");
            throw new Exception("請先執(zhí)行init()");
        }
    }
}

3.3.4 文件下載

JSch文件下載是通過調(diào)用ChannelSftp對象的get方法來實現(xiàn)的。ChannelSftp中有9個get方法的重載方法:

方法描述
publicvoid get(String src, String dst)將目標服務(wù)器上文件名為src的文件下載到本地,本地文件名為dst。若dst為目錄,則下載到本地的文件名將與src文件名相同。(注:src必須是文件,不能為目錄),采用默認的傳輸模式:OVERWRITE
publicvoid get(String src, String dst, SftpProgressMonitor monitor)將目標服務(wù)器上文件名為src的文件下載到本地,本地文件名為dst。若dst為目錄,則下載到本地的文件名將與src文件名相同。(注:src必須是文件,不能為目錄),采用默認的傳輸模式:OVERWRITE
publicvoid get(String src, String dst,SftpProgressMonitor monitor, int mode)將目標服務(wù)器上文件名為src的文件下載到本地,本地文件名為dst。若dst為目錄,則下載到本地的文件名將與src文件名相同。(注:src必須是文件,不能為目錄)指定文件傳輸模式為mode(mode可選值為:ChannelSftp.OVERWRITE,ChannelSftp.RESUME,ChannelSftp.APPEND),并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控文件的傳輸進度。
publicvoid get(String src, OutputStream dst)將目標服務(wù)器上文件名為src的文件下載到本地,下載的數(shù)據(jù)寫入到輸出流對象dst(如:文件輸出流)。采用默認的傳輸模式:OVERWRITE
publicvoid get(String src, OutputStream dst, SftpProgressMonitor monitor)將目標服務(wù)器上文件名為src的文件下載到本地,下載的數(shù)據(jù)寫入到輸出流對象dst(如:文件輸出流)。采用默認的傳輸模式:OVERWRITE,并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控文件的傳輸進度。
publicvoid get(String src, OutputStream dst, SftpProgressMonitor monitor, int mode, long skip)將目標服務(wù)器上文件名為src的文件下載到本地,下載的數(shù)據(jù)寫入到輸出流對象dst(如:文件輸出流)。指定文件傳輸模式為mode并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控文件的傳輸進度。skip指定了一個跳讀量,即下載時從src文件跳過skip字節(jié)的數(shù)據(jù)。(一般不推薦使用該參數(shù),默認設(shè)為0)
public InputStream get(String src)該方法返回一個輸入流,該輸入流含有目標服務(wù)器上文件名為src的文件數(shù)據(jù)??梢詮脑撦斎肓髦凶x取數(shù)據(jù),最終將數(shù)據(jù)傳輸?shù)奖镜兀ㄈ纾鹤x取數(shù)據(jù)后將數(shù)據(jù)寫入到本地的文件中)(注:該方法不支持多種文件傳輸模式,如何讀取與保存數(shù)據(jù)由應(yīng)用程序自己確定)
public InputStream get(String src, SftpProgressMonitor monitor)該方法返回一個輸入流,該輸入流含有目標服務(wù)器上文件名為src的文件數(shù)據(jù)??梢詮脑撦斎肓髦凶x取數(shù)據(jù),最終將數(shù)據(jù)傳輸?shù)奖镜兀ㄈ纾鹤x取數(shù)據(jù)后將數(shù)據(jù)寫入到本地的文件中)并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控文件的傳輸進度。(注:該方法不支持多種文件傳輸模式,如何讀取與保存數(shù)據(jù)由應(yīng)用程序自己確定)
public InputStream get(String src, final SftpProgressMonitor monitor, finallong skip)該方法返回一個輸入流,該輸入流含有目標服務(wù)器上文件名為src的文件數(shù)據(jù)??梢詮脑撦斎肓髦凶x取數(shù)據(jù),最終將數(shù)據(jù)傳輸?shù)奖镜兀ㄈ纾鹤x取數(shù)據(jù)后將數(shù)據(jù)寫入到本地的文件中)并使用實現(xiàn)了SftpProgressMonitor接口的monitor對象來監(jiān)控文件的傳輸進度。(注:該方法不支持多種文件傳輸模式,如何讀取與保存數(shù)據(jù)由應(yīng)用程序自己確定)skip指定了一個跳讀量,即下載時從src文件跳過skip字節(jié)的數(shù)據(jù)。(一般不推薦使用該參數(shù),默認設(shè)為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代碼

/**
     * 執(zhí)行復雜shell命令
     * @param cmds 多條命令
     * @return 執(zhí)行結(jié)果
     * @throws Exception 連接異常
     */
    public String execCmdByShell(String... cmds)throws Exception{
        return execCmdByShell(Arrays.asList(cmds));
    }
 /**
     * 執(zhí)行復雜shell命令
     * @param cmds 多條命令
     * @return 執(zhí)行結(jié)果
     * @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 {
        // 打開執(zhí)行shell指令的通道
        channel = session.openChannel("shell");
        channelShell = (ChannelShell) channel;
        if (session == null || channel == null || channelShell == null) {
            log.error("請先執(zhí)行init()");
            throw new Exception("請先執(zhí)行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);
    }
    /**
     * 連接多次執(zhí)行命令,執(zhí)行命令完畢后需要執(zhí)行close()方法
     *
     * @param command 需要執(zhí)行的指令
     * @return 執(zhí)行結(jié)果
     * @throws Exception 沒有執(zhí)行初始化
     */
    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();
        }
    }
    /**
     * 執(zhí)行命令關(guān)閉連接
     *
     * @param command 需要執(zhí)行的指令
     * @return 執(zhí)行結(jié)果
     * @throws Exception 沒有執(zhí)行初始化
     */
    public String execCmdAndClose(String command) throws Exception {
        String result = execCmd(command);
        close();
        return result;
    }
    /**
     * 執(zhí)行復雜shell命令
     *
     * @param cmds 多條命令
     * @return 執(zhí)行結(jié)果
     * @throws Exception 連接異常
     */
    public String execCmdByShell(String... cmds) throws Exception {
        return execCmdByShell(Arrays.asList(cmds));
    }
    /**
     * 執(zhí)行復雜shell命令
     *
     * @param cmds 多條命令
     * @return 執(zhí)行結(jié)果
     * @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文件上傳并監(jiān)控上傳進度
     *
     * @param src 源地址
     * @param dst 目的地址
     * @throws Exception 上傳文件失敗
     */
    public void putMonitorAndClose(String src, String dst) throws Exception {
        putMonitorAndClose(src, dst, ChannelSftp.OVERWRITE);
    }
    /**
     * SFTP文件上傳并監(jiān)控上傳進度
     *
     * @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文件下載并監(jiān)控下載進度
     *
     * @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("請先執(zhí)行init()");
            throw new Exception("請先執(zhí)行init()");
        }
    }
    private void initChannelExec() throws Exception {
        // 打開執(zhí)行shell指令的通道
        channel = session.openChannel("exec");
        channelExec = (ChannelExec) channel;
        if (session == null || channel == null || channelExec == null) {
            log.error("請先執(zhí)行init()");
            throw new Exception("請先執(zhí)行init()");
        }
    }
    private void initChannelShell() throws Exception {
        // 打開執(zhí)行shell指令的通道
        channel = session.openChannel("shell");
        channelShell = (ChannelShell) channel;
        if (session == null || channel == null || channelShell == null) {
            log.error("請先執(zhí)行init()");
            throw new Exception("請先執(zhí)行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();
            // 判斷當前已傳輸數(shù)據(jù)大小是否等于文件總大小
            if (transfered != fileSize) {
                log.info("Current transfered: {} bytes", transfered);
                sendProgressMessage(transfered);
            } else {
                // 如果當前已傳輸數(shù)據(jù)大小等于文件總大小,說明已完成,設(shè)置end
                log.info("File transfering is done.");
                setEnd(true);
            }
        } else {
            log.info("Transfering done. Cancel timer.");
            // 如果傳輸結(jié)束,停止timer記時器
            stop();
            return;
        }
    }
    /**
     * 實現(xiàn)了SftpProgressMonitor接口的count方法
     */
    @Override
    public boolean count(long count) {
        if (isEnd()) {
            return false;
        }
        if (!isScheduled) {
            start();
        }
        add(count);
        return true;
    }
    /**
     * 實現(xiàn)了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秒鐘后開始執(zhí)行,每2杪鐘執(zhí)行一次
        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連接池

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Java中String,StringBuffer和StringBuilder的使用

    詳解Java中String,StringBuffer和StringBuilder的使用

    這篇文章主要為大家詳細介紹了Java中String,StringBuffer和StringBuilder三者的區(qū)別以及使用,文中的少了講解詳細,感興趣的可以了解一下
    2022-07-07
  • Go Java算法之解碼方法示例詳解

    Go Java算法之解碼方法示例詳解

    這篇文章主要為大家介紹了Go Java算法之解碼方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Spring系列中的beanFactory與ApplicationContext

    Spring系列中的beanFactory與ApplicationContext

    這篇文章主要介紹了Spring系列中的beanFactory與ApplicationContext,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • JAVA堆排序算法的講解

    JAVA堆排序算法的講解

    這篇文章主要介紹了JAVA堆排序算法的知識點,文中代碼非常詳細,配合上圖片講解,幫助大家更好的參考和學習,感興趣的朋友可以了解下
    2020-06-06
  • Java 如何優(yōu)雅的拋出業(yè)務(wù)異常

    Java 如何優(yōu)雅的拋出業(yè)務(wù)異常

    這篇文章主要介紹了Java 如何優(yōu)雅的拋出業(yè)務(wù)異常,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-12-12
  • SpringBoot集成Zipkin實現(xiàn)分布式全鏈路監(jiān)控

    SpringBoot集成Zipkin實現(xiàn)分布式全鏈路監(jiān)控

    這篇文章主要介紹了SpringBoot集成Zipkin實現(xiàn)分布式全鏈路監(jiān)控的方法啊,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • 深入淺析ZooKeeper的工作原理

    深入淺析ZooKeeper的工作原理

    ZooKeeper 是一個開源的分布式協(xié)調(diào)服務(wù),由雅虎創(chuàng)建,是 Google Chubby 的開源實現(xiàn)。接下來通過本文跟大家介紹ZooKeeper的原理,小編覺得挺不錯的,感興趣的小伙伴們可以參考一下
    2018-05-05
  • java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用實戰(zhàn)

    java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用實戰(zhàn)

    這篇文章主要介紹了java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用,結(jié)合實例形式分析了java枚舉類的定義、構(gòu)造及相關(guān)應(yīng)用操作技巧,需要的朋友可以參考下
    2019-08-08
  • java不同線程解讀以及線程池的使用方式

    java不同線程解讀以及線程池的使用方式

    這篇文章主要介紹了java不同線程解讀以及線程池的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • SpringBoot使用Prometheus采集自定義指標數(shù)據(jù)的方法詳解

    SpringBoot使用Prometheus采集自定義指標數(shù)據(jù)的方法詳解

    隨著微服務(wù)在生產(chǎn)環(huán)境大規(guī)模部署和應(yīng)用,隨之而來也帶來了新的問題,其中比較關(guān)鍵的就是關(guān)于微服務(wù)的運維和監(jiān)控,本文將結(jié)合微服務(wù)運維監(jiān)控中的指標監(jiān)控進行詳細的說明,需要的朋友可以參考下
    2024-07-07

最新評論