JSch实践(一)简介和远程文件的操作

Sftp
placeholder image
admin 发布于:2023-11-24 14:40:46
阅读:loading

1.基本介绍

(1)JSch是Java Secure Channel的缩写,是一个JAVA实现的SSH2协议的开源库。它提供了在Java程序中进行SSH(Secure Shell)连接和通信的功能,官网地址为:“http://www.jcraft.com/jsch/”、“https://github.com/is/jsch”。

(2)JSch可以用于在Java程序中连接到远程服务器,并执行远程命令、传输文件等操作。它对SSH2协议的支持非常完整,并且提供了丰富的API和功能,使得开发人员能够轻松地编写出与SSH服务器进行交互的Java程序。

(3)JSch的主要特点包括:

A. 支持SSH2协议的主要功能,包括认证、加密、数据压缩等。

B. 提供了丰富的API,可以方便地进行SSH连接、执行命令、传输文件等操作。

C. 支持各种身份验证方式,包括密码、公钥和代理等。

D. 可以通过端口转发和X11转发等功能实现远程端口和图形界面的访问。

E. 提供了丰富的错误处理和调试功能,方便开发人员进行故障排查。

(4)使用JSch可以方便地在Java程序中与远程服务器进行交互,进行自动化的任务和批处理操作。它广泛应用于各种Java项目中,包括远程服务器管理、自动化部署、网络设备管理等领域。

2.组件特征

JSch 是一个用于在Java中实现SSH(Secure Shell)连接的库。它提供了一种在Java应用程序中进行远程执行命令、传输文件和使用端口转发等操作的方式。以下是一些使用 JSch 的原因:

(1)远程执行命令: JSch 允许你在远程服务器上执行命令,这对于自动化部署、系统管理和远程监控等任务非常有用。

(2)文件传输: 通过 JSch,你可以在本地和远程系统之间进行文件传输。这对于备份、同步和文件管理等操作是必需的。

(3)端口转发: JSch 支持端口转发,这是一种将本地端口与远程端口关联的技术。这在安全通信和访问受限资源时非常有用。

(4)安全性: SSH 提供了加密通信和身份验证机制,确保数据传输的安全性。JSch 利用了SSH协议的这些特性,使得在Java应用程序中进行安全的远程通信成为可能。

(5)跨平台性: 由于 JSch 是用Java编写的,它是跨平台的。这意味着你可以在不同的操作系统上使用相同的代码来实现远程连接,而不用担心平台差异。

总体而言,JSch是一个强大的工具,适用于需要在Java应用程序中实现与远程服务器的安全通信和操作的场景。

3.文件传输

ChannelSftp是JSch提供的用于进行 SFTP(SSH 文件传输协议)操作的类。它提供了一系列的方法,可用于上传、下载、重命名、删除文件,创建和删除目录,以及列出远程目录的内容,参考如下示例:

(1)文件上传

/**
 * 上传文件
 */
@Test
public void uploadFileTest() throws Exception {
    SftpUtils sftp = SftpUtils.newInstance(new SftpParam());
    try {
        String file = getClass().getResource("SftpTest.class").getFile();
        sftp.uploadFile(file , "/app/arthas/arthas-class/SftpTest.class");
    } finally {
        sftp.disconnect();
    }
}

(2)文件下载

/**
 * 下载文件
 */
@Test
public void downloadFileTest() throws Exception {
    SftpUtils sftp = SftpUtils.newInstance(new SftpParam());
    try {
        File destFile = new File(FileUtils.getTempDirectory() , "SftpTest.class");
        sftp.downloadFile("/app/arthas/arthas-class/SftpTest.class" , destFile.getPath());
        Assert.assertTrue(destFile.exists());
    } finally {
        sftp.disconnect();
    }
}

(3)文件夹列表

/**
 * 获取文件夹列表
 */
@Test
public void listFileTest() throws Exception {
    SftpUtils sftp = SftpUtils.newInstance(new SftpParam());
    try {
        List<SftpUtils.FileEntry> files = sftp.listFiles("/app/arthas/arthas-class");
        for (SftpUtils.FileEntry file : files) {
            System.out.println((file.isDir() ? "文件夹  " : "文件    ") + file.getLongname());
        }
    } finally {
        sftp.disconnect();
    }
}

(4)SftpUtils工具类

/**
 * sftp操作工具类
 *
 * @author chendd
 * @date 2023/11/18 9:12
 */
@Getter
public final class SftpUtils {

    /**
     * 路径分隔符
     */
    private static final String SEPARATOR = "/";

    private Session session;

    private ChannelSftp channel;

    /**
     * 根据sftp连接参数获取工具类实例
     * @param param 参数对象
     * @return 工具类实例
     */
    public static SftpUtils newInstance(SftpParam param) {
        JSch jsch = new JSch();
        SftpUtils sftp = new SftpUtils();
        try {
            sftp.session = jsch.getSession(param.getUsername(), param.getHost(), param.getPort());
            final String password = param.getPassword();
            if (StringUtils.isNotEmpty(password)) {
                sftp.session.setPassword(password);
            }
            sftp.session.setTimeout(param.getTimeout());
            sftp.session.setConfig("StrictHostKeyChecking" , "no");
            sftp.session.connect();
            sftp.channel = (ChannelSftp) sftp.session.openChannel("sftp");
            sftp.channel.connect();
        } catch (JSchException e) {
            if (sftp.session != null) {
                sftp.session.disconnect();
            }
            throw new RuntimeException(e);
        }
        return sftp;
    }

    /**
     * 上传文件【默认覆盖】
     * @param src 本地源文件路径
     * @param dest 远程目标路径
     */
    public void uploadFile(String src, String dest) throws SftpException {
        this.channel.put(src , dest);
    }

    /**
     * 下载文件
     * @param src 远程源文件
     * @param dest 本地目标文件
     */
    public void downloadFile(String src, String dest) throws SftpException {
        this.channel.get(src , dest);
    }
    
    //......更多
}

(5)运行结果

JSch获取远程目录列表.gif

4.其它说明

(1)本次实践JSch共计三块知识,分别是使用Sftp访问远程服务器、Exec执行远程服务器命令、Shell执行远程服务器命令,至于它还可以作用于的端口转发等功能不做摸索,官方在“http://www.jcraft.com/jsch/examples/”提供了一些示例可以参考;

(2)本文实现了JSch实现文件的上传、下载、删除、重命名、文件列表、路径是否存在等多个常用的功能,完整示例工程代码可见《附件下载.zip

(3)工具类代码的封装像极了使用原生JDBC操作数据库的实现:① 每个方法都需要处理异常;② 每次操作都获取 Connection连接,使用完后关闭连接;

(4)工具类代码的封装应该以池化的形式,可以使用Apache Commons pool组件进行连接池的方式管理,在实际应用中将会更加科学;

5.同类组件对比

所谓的同类组件是指使用Java来操作远程Linux服务器,包含对远程服务器对文件的操作、Shell命令的执行等,本次代码是对相关的组件JSch和Apache Mina SSHD项目的案例实践,以下是个人以为的区别:

(1)JSch组件最后的更新是2018年的,已经不再更新了,而Apache Mina SSHD最新版本的更新仍然是2023年(今年),更新维护仍在继续;

(2)JSch组件的核心API代码均抛出组件内的自定义异常(JSchException),而Apache Mina SSHD抛出的是Java中常见的IOException;

(3)JSch组件的核心API代码偏重于自身内部的定义,而Apache Mina SSHD侧重于对Java nio文件操作的API,更加现代化一些;

(4)JSch组件主要提供了Sftp Client客户端的操作,而Apache Mina SSHD不仅提供了SSH Client,还有提供SSH Server端,功能更加丰富;

(5)JSch组件不依赖于其它组件,而Apache Mina SSHD细分了挺多的功能module,同时也集成了日志框架Slf4j;

(6)二者的API的封装和使用非常相似;

所以,我个人更加推荐有同类的需求时使用Apache Mina SSHD。


 点赞


 发表评论

当前回复:作者

 评论列表


留言区