SFTP使用JSCH库链接不断开解决方法

来源:互联网 发布:js round 编辑:程序博客网 时间:2024/05/16 15:43

在处理银行业务的时候,数据交互还使用老旧的sftp技术,最近在使用sftp的JSCH库时发现,采用公私钥方式连接server,总是无法断开连接,研究发现这种模式下如果存在并发的链接时,disconnect方法实际不起左右,这样会产生大量链接,最终造成无法再链接上;解决办法采用Threadlocal镜像复制方式,为每个链接建立单独的工具对象


public class SftpUtil {    private final static Logger          log       = LoggerFactory.getLogger(SftpUtil.class);    /** SFTP */    public static final String           SFTP      = "sftp";    /** 通道 */    private ChannelSftp                  channel;    /** session */    private Session                      session;    /** 规避多线程并发不断开问题 */    private static ThreadLocal<SftpUtil> sftpLocal = new ThreadLocal<SftpUtil>();    /**     * 获取sftpchannel     *      * @param connectConfig 连接配置     * @return     * @throws Exception      * @throws JSchException     */    private void init(ConnectConfig connectConfig) throws Exception {        String host = connectConfig.getHost();        int port = connectConfig.getPort();        String userName = connectConfig.getUserName();        //创建JSch对象        JSch jsch = new JSch();        //添加私钥(信任登录方式)        if (StringUtils.isNotBlank(connectConfig.getPrivateKey())) {            jsch.addIdentity(connectConfig.getPrivateKey());        }        session = jsch.getSession(userName, host, port);        if (log.isInfoEnabled()) {            log.info(" JSCH Session created,sftpHost = {}, sftpUserName={}", host, userName);        }        //设置密码        if (StringUtils.isNotBlank(connectConfig.getPassWord())) {            session.setPassword(connectConfig.getPassWord());        }        Properties config = new Properties();        config.put("StrictHostKeyChecking", "no");        session.setConfig(config);        //设置超时        session.setTimeout(connectConfig.getTimeout());        //建立连接        session.connect();        if (log.isInfoEnabled()) {            log.info("JSCH Session connected.sftpHost = {}, sftpUserName={}", host, userName);        }        //打开SFTP通道        channel = (ChannelSftp) session.openChannel(SFTP);        //建立SFTP通道的连接        channel.connect();        if (log.isInfoEnabled()) {            log.info("Connected successfully to sftpHost = {}, sftpUserName={}", host, userName);        }    }    /**     * 是否已连接     *      * @return     */    private boolean isConnected() {        return null != channel && channel.isConnected();    }    /**     * 获取本地线程存储的sftp客户端     *      * @return     * @throws Exception      */    public static SftpUtil getSftpUtil(ConnectConfig connectConfig) throws Exception {        SftpUtil sftpUtil = sftpLocal.get();        if (null == sftpUtil || !sftpUtil.isConnected()) {            sftpLocal.set(new SftpUtil(connectConfig));        }        return sftpLocal.get();    }    /**     * 释放本地线程存储的sftp客户端     */    public static void release() {        if (null != sftpLocal.get()) {            sftpLocal.get().closeChannel();            sftpLocal.set(null);        }    }    /**     * 构造函数     * <p>     * 非线程安全,故权限为私有     * </p>     *      * @throws Exception      */    private SftpUtil(ConnectConfig connectConfig) throws Exception {        super();        init(connectConfig);    }    /**     * 关闭通道     *      * @throws Exception     */    public void closeChannel() {        if (null != channel) {            try {                channel.disconnect();            } catch (Exception e) {                log.error("关闭SFTP通道发生异常:", e);            }        }        if (null != session) {            try {                session.disconnect();            } catch (Exception e) {                log.error("SFTP关闭 session异常:", e);            }        }    }    /**     * 下载文件     *      * @param downDir 下载目录     * @param src 源文件     * @param dst 保存后的文件名称或目录     * @throws Exception     */    public void downFile(String downDir, String src, String dst) throws Exception {        channel.cd(downDir);        channel.get(src, dst);    }    /**     * 删除文件     *      * @param filePath 文件全路径     * @throws SftpException     */    public void deleteFile(String filePath) throws SftpException {        channel.rm(filePath);    }    @SuppressWarnings("unchecked")    public List<String> listFiles(String dir) throws SftpException {        Vector<LsEntry> files = channel.ls(dir);        if (null != files) {            List<String> fileNames = new ArrayList<String>();            Iterator<LsEntry> iter = files.iterator();            while (iter.hasNext()) {                String fileName = iter.next().getFilename();                if (StringUtils.equals(".", fileName) || StringUtils.equals("..", fileName)) {                    continue;                }                fileNames.add(fileName);            }            return fileNames;        }        return null;    }}

0 0