关于Springboot中JSCH的使用及说明

次元: 365betapp下载 时间戳: 2026-02-21 08:06:35 观察者: admin 访问量: 9112 能量值: 502
关于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依赖

com.jcraft

jsch

0.1.55

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

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

相关维度

学琴须知 || 古琴丝弦的规格

学琴须知 || 古琴丝弦的规格

有没有感觉,世界杯历史上三个任意球配合破门,一个比一个粗糙

有没有感觉,世界杯历史上三个任意球配合破门,一个比一个粗糙

如何使用手机QQ解散QQ群

如何使用手机QQ解散QQ群

《魔兽世界》奥格瑞玛学骑术位置介绍

《魔兽世界》奥格瑞玛学骑术位置介绍