最近使用JSch进行sftp文件上传下载,直接在官网找到样例使用,但在并发情景下并不理想,分析代码,发现每次都会新建session,代码如下:
JSch jsch = new JSch();
session = jsch.getSession(username, serverIp, serverPort);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
查看connect()方法,发现每次都会新建socket连接,如下:
socket=Util.createSocket(host, port, connectTimeout); in=socket.getInputStream(); out=socket.getOutputStream();
正如上面展示的,每次上传文件都会新建socket连接,这是极大的资源浪费,修改代码维护session,做到session复用,在类中添加session属性,添加如下方法:
private String ip;
private int port;
private String password;
private String username;
private Session session = null;
public void connect() throws JSchException {
try {
if (session == null || !session.isConnected()) {
synchronized (this) {
if (session == null || !session.isConnected()) {
JSch jsch = new JSch();
session = jsch.getSession(username, ip, port);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
}
}
}
} catch (JSchException e) {
throw e;
}
}
public void disconnect() {
if (this.session != null) {
if (this.session.isConnected()) {
this.session.disconnect();
if (log.isInfoEnabled()) {
log.info("session is closed");
}
}
}
}
编写上传下载方法时复用同一个session,示例如下:
public void upload(String path, String fileName, InputStream input) throws SftpException, JSchException {
ChannelSftp sftp;
try {
sftp = (ChannelSftp) session.openChannel("sftp")
sftp.connect();
} catch (JSchException e) {
throw e;
}
try {
if (sftp.ls(path) == null) {
sftp.mkdir(path);
}
sftp.cd(path);
} catch (SftpException e) {
sftp.mkdir(path);
sftp.cd(path);
}
try {
sftp.put(input, fileName);
} catch (Exception e) {
throw e;
} finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
log.error("input close fail",e);
}
}
if (sftp != null) {
if (sftp.isConnected()) {
sftp.disconnect();
log.info("sftp disconnect");
}
}
}
}



