背景
在项目开发中,一般文件存储很少再使用SFTP服务,但是也不排除合作伙伴使用SFTP来存储项目中的文件或者通过SFTP来实现文件数据的交互。我遇到的项目中,就有银行和保险公司等合作伙伴通过SFTP服务来实现与我们项目的文件数据的交互。
为了能够顺利地完成与友商的SFTP服务的连通,我们需要在自己的项目中实现一套SFTP客户端工具。一般我们会采用Jsch来实现SFTP客户端。
依赖
<!--执行远程操作-->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
<!--链接池-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.11.1</version>
</dependency>
复制代码
首先我们一定要引入jsch
依赖,这个是我们实现SFTP客户端的基石;其次我们引入了链接池工具,为了避免每次执行SFTP命令都要重新创建链接,我们使用池化的方式优化了比较消耗资源的创建操作。
创建工具类
为了更好的使用SFTP工具,我们把jsch
中关于SFTP的相关功能提炼出来,做了一次简单的封装,做成了我们可以直接使用的工具类。
里面只有两类方法:
1.创建Session与开启Session;
session创建好后,还不能创建channel,需要开启session后才能创建channel;
2.创建channel与开启channel;
channel也是一样,创建好的channel需要开启后才能真正地执行命令;
public class JschUtil {
/**
* 创建session
*
* @param userName 用户名
* @param password 密码
* @param host 域名
* @param port 端口
* @param privateKeyFile 密钥文件
* @param passphrase 口令
* @return
* @throws AwesomeException
*/
public static Session createSession(String userName, String password, String host, int port, String privateKeyFile, String passphrase) throws AwesomeException {
return createSession(new JSch(), userName, password, host, port, privateKeyFile, passphrase);
}
/**
* 创建session
*
* @param jSch
* @param userName 用户名
* @param password 密码
* @param host 域名
* @param port 端口
* @param privateKeyFile 密钥
* @param passphrase 口令
* @return
* @throws AwesomeException
*/
public static Session createSession(JSch jSch, String userName, String password, String host, int port, String privateKeyFile, String passphrase) throws AwesomeException {
try {
if (!StringUtils.isEmpty(privateKeyFile)) {
// 使用密钥验证方式,密钥可以是有口令的密钥,也可以是没有口令的密钥
if (!StringUtils.isEmpty(passphrase)) {
jSch.addIdentity(privateKeyFile, passphrase);
} else {
jSch.addIdentity(privateKeyFile);
}
}
// 获取session
Session session = jSch.getSession(userName, host, port);
if (!StringUtils.isEmpty(password)) {
session.setPassword(password);
}
// 不校验域名
session.setConfig("StrictHostKeyChecking", "no");
return session;
} catch (Exception e) {
throw new AwesomeException(500, "create session fail");
}
}
/**
* 创建session
*
* @param jSch
* @param userName 用户名
* @param password 密码
* @param host 域名
* @param port 端口
* @return
* @throws AwesomeException
*/
public static Session createSession(JSch jSch, String userName, String password, String host, int port) throws AwesomeException {
return createSession(jSch, userName, password, host, port, StringUtils.EMPTY, StringUtils.EMPTY);
}
/**
* 创建session
*
* @param jSch
* @param userName 用户名
* @param host 域名
* @param port 端口
* @return
* @throws AwesomeException
*/
private Session createSession(JSch jSch, String userName, String host, int port) throws AwesomeException {
return createSession(jSch, userName, StringUtils.EMPTY, host, port, StringUtils.EMPTY, StringUtils.EMPTY);
}
/**
* 开启session链接
*
* @param jSch
* @param userName 用户名
* @param password 密码
* @param host 域名
* @param port 端口
* @param privateKeyFile 密钥
* @param passphrase 口令
* @param timeout 链接超时时间
* @return
* @throws AwesomeException
*/
public static Session openSession(JSch jSch, String userName, String password, String host, int port, String privateKeyFile, String passphrase, int timeout) throws AwesomeException {
Session session = createSession(jSch, userName, password, host, port, privateKeyFile, passphrase);
try {
if (timeout >= 0) {
session.connect(timeout);
} else {
session.connect();
}
return session;
} catch (Exception e) {
throw new AwesomeException(500, "session connect fail");
}
}
/**
* 开启session链接
*
* @param userName 用户名
* &