common pool实现sftp连接池

记录一下common pool实现连接池的方法。

  • GenericObjectPool(租车公司)
  • PooledObject(租车公司的所有车辆)
  • BorrowObject(租车)
  • ReturnObject(还车)
  • TestOnBorrow/TestOnReturn(租出/归还时进行检查)
  • EvictThread(定期检查的安检人员)

sftp的依赖:

<dependency>
   <groupId>com.jcraft</groupId>
   <artifactId>jsch</artifactId>
   <version>0.1.55</version>
</dependency>

1.先定义连接池配置信息,get/set方法在此省略。

public class PoolConfigInfo {
    /**
     * 池中最小的连接数,只有当 timeBetweenEvictionRuns 为正时才有效
     */
    private int minIdle;
    /**
     * 池中最大的空闲连接数,为负值时表示无限
     */
    private int maxIdle;
    /**
     * 池可以产生的最大对象数,为负值时表示无限
     */
    private int maxTotal;
    /**
     * 当池耗尽时,阻塞的最长时间,为负值时无限等待
     */
    private long maxWait;
    /**
     * 从池中取出对象是是否检测可用
     */
    private boolean testOnBorrow;
    /**
     * 将对象返还给池时检测是否可用
     */
    private boolean testOnReturn;
    /**
     * 检查连接池对象是否可用
     */
    private boolean testWhileIdle;
    /**
     * 距离上次空闲线程检测完成多久后再次执行
     */
    private long timeBetweenEvictionRuns;
}

2.后续channel需要的参数准备,在此get/set方法也省略掉了。

public class SftpProperties {
    /**
     * 地址
     */
    private String sshHost;
    /**
     * 端口号
     */
    private int sshPort = 22;
    /**
     * 用户名
     */
    private String userName;
    /**
     * 密码
     */
    private String pwd;
    /**
     * 连接池配置
     */
    private PoolConfigInfo pool;
}

3.连接池

public class SftpPool implements ObjectPool<ChannelSftp> {
    private final GenericObjectPool<ChannelSftp> channelPool;
    private Session session;

    public SftpPool(SftpProperties sftpProperties) throws JSchException {
        JSch jsch = new JSch();
        this.session = jsch.getSession(sftpProperties.getUserName(), sftpProperties.getSshHost(), sftpProperties.getSshPort());
        session.setPassword(sftpProperties.getPwd());
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();
        this.channelPool= new GenericObjectPool<ChannelSftp>(new SftpPoolFactory(sftpProperties, session), getPoolConfig(sftpProperties.getPool()));
    }

    @Override
    public void addObject() throws Exception {
        channelPool.addObject();
    }


    private ChannelSftp checkChannel(ChannelSftp channelSftp) throws Exception 		{
        if(channelSftp.isConnected()){
            return channelSftp;
        } else {
            channelPool.invalidateObject(channelSftp);
            ChannelSftp newChannelSftp= channelPool.borrowObject();
            return newChannelSftp;
        }
    }

    @Override
    public ChannelSftp borrowObject() throws Exception {
        ChannelSftp channelSftp = channelPool.borrowObject();
        channelSftp=checkChannel(channelSftp);
        return channelSftp;
    }

    @Override
    public void clear() {
        channelPool.clear();
    }

    @Override
    public void close() {
        channelPool.close();
        session.disconnect();
    }

    @Override
    public int getNumActive() {
        return channelPool.getNumActive();
    }

    @Override
    public int getNumIdle() {
        return channelPool.getNumIdle();
    }

    @Override
    public void invalidateObject(ChannelSftp channelSftp) throws Exception {
        channelPool.invalidateObject(channelSftp);
    }

    @Override
    public void returnObject(ChannelSftp channelSftp){
        channelPool.returnObject(channelSftp);
    }

    private GenericObjectPoolConfig getPoolConfig(PoolConfigInfo properties) {
        if (properties == null) {
            properties = new PoolConfigInfo();
        }
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        config.setMinIdle(properties.getMinIdle());
        config.setMaxIdle(properties.getMaxIdle());
        config.setMaxTotal(properties.getMaxTotal());
        config.setMaxWaitMillis(properties.getMaxWait());
        config.setTestOnBorrow(properties.isTestOnBorrow());
        config.setTestOnReturn(properties.isTestOnReturn());
        config.setTestWhileIdle(properties.isTestWhileIdle());
        config.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRuns());
        return config;
    }
}
public class SftpPoolFactory extends BasePooledObjectFactory<ChannelSftp> {

    private final SftpProperties sftpProperties;
    private Session session;

    public SftpPoolFactory(SftpProperties sftpProperties, Session session) {
        this.sftpProperties = sftpProperties;
        this.session = session;
    }

    @Override
    public ChannelSftp create() throws JSchException {
        ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
        try {
            channelSftp.connect();
        } catch (Exception ex) {
            throw new RuntimeException("sftp连接数不够了~", ex);
        }
        return channelSftp;
    }

    @Override
    public PooledObject<ChannelSftp> wrap(ChannelSftp channelSftp) {
        return new DefaultPooledObject<>(channelSftp);
    }

    @Override
    public boolean validateObject(PooledObject<ChannelSftp> pChannelSftp) {
        return pChannelSftp.getObject().isConnected();
    }

    @Override
    public void destroyObject(PooledObject<ChannelSftp> pChannelSftp) {
        pChannelSftp.getObject().disconnect();
    }
}

4.实际操作方法

public class SftpOperate implements Closeable {
    private SftpProperties sftpProperties;
    private SftpPool sftpPool;
    private PoolConfigInfo poolConfig;
    private String initDir;

    public SftpOperate(sftpConfig config){
        //在这里校验一下配置信息
        
        //组装连接池参数
        getPoolConfigInfo();

        //组装配置
        boxProperties();
        //从连接池中创建连接
        try {
            sftpPool=new SftpPool(sftpProperties);
        } catch (Exception e) {
            throw new RuntimeException("sftp失败", e);
        }
    }


    public ChannelSftp borrow() {
        ChannelSftp channelSftp= null;
        try {
            channelSftp = sftpPool.borrowObject();
            if(StringUtil.isEmpty(initDir)){
                initDir=channelSftp.pwd();
            }
        } catch (Exception e) {
            throw new RuntimeException("获取sftp连接出错!", e);
        }
        return channelSftp;
    }

    public void returnChannelSftp(ChannelSftp channelSftp){
        try {
            channelSftp.cd(initDir);
            sftpPool.returnObject(channelSftp);
        } catch (SftpException e) {
            try {
                sftpPool.invalidateObject(channelSftp);
            } catch (Exception ignore) {
            }
        }
    }

    @Override
    public void close() throws IOException {
        sftpPool.close();
    }

    public void getPoolConfigInfo() {
        poolConfig=new PoolConfigInfo();
        poolConfig.setMinIdle(2);
        poolConfig.setMaxIdle(6);
        poolConfig.setMaxTotal(6);
        poolConfig.setMaxWait(-1L);
        poolConfig.setTestOnBorrow(false);
        poolConfig.setTestOnReturn(false);
        poolConfig.setTestWhileIdle(true);
        poolConfig.setTimeBetweenEvictionRuns(300000L);
    }

    public void boxProperties(){
        String sshHost="127.0.0.1";
        int sshPort=22;
        sftpProperties=new SftpProperties();
        sftpProperties.setSshHost(sshHost);
        sftpProperties.setSshPort(sshPort);
        sftpProperties.setUserName("username");
        sftpProperties.setPwd("pwd");
        sftpProperties.setPool(poolConfig);
    }

    @Override
    public boolean exists(String path) {
        ChannelSftp channelSftp=borrow();
        try {
            return isExist(channelSftp,path, true);
        } catch (Exception e) {
            throw new RuntimeException("sftp失败", e);
        }finally {
            returnChannelSftp(channelSftp);
        }
    }

    @Override
    public void createDir(String path) {
        ChannelSftp channelSftp=borrow();
        try {
            createDir(channelSftp,path);
        } catch (Exception e) {
            throw new RuntimeException("sftp失败", e);
        }finally {
            returnChannelSftp(channelSftp);
        }
    }

    @Override
    public boolean exists(String path, String fileName) {
        ChannelSftp channelSftp=borrow();
        try {
            return isExist(channelSftp,path + "/" + fileName, true);
        } catch (Exception e) {
            throw new RuntimeException("sftp失败", e);
        }finally {
            returnChannelSftp(channelSftp);
        }
    }

    @Override
    public InputStream read(String path, String fileName) {
        ChannelSftp channelSftp=borrow();
        try {
            return downloadStream(channelSftp,path, fileName);
        } catch (Exception e) {
            throw new RuntimeException("sftp失败", e);
        }finally {
            returnChannelSftp(channelSftp);
        }
    }

    @Override
    public void write(String path, String fileName, File file) {
        ChannelSftp channelSftp=borrow();
        try {
            upload(channelSftp,path,fileName,Files.newInputStream(file.toPath()));
        } catch (Exception e) {
            throw new RuntimeException("sftp失败", e);
        }finally {
            returnChannelSftp(channelSftp);
        }
    }

    @Override
    public void write(String path, String fileName, byte[] arr) {
        ChannelSftp channelSftp=borrow();
        try {
            upload(channelSftp,path,fileName,arr);
        } catch (Exception e) {
            throw new RuntimeException("sftp失败", e);
        }finally {
            returnChannelSftp(channelSftp);
        }
    }

    @Override
    public void write(String path, String fileName, InputStream inputStream) {
        ChannelSftp channelSftp=borrow();
        try {
            upload(channelSftp,path,fileName,inputStream);
        } catch (Exception e) {
            throw new RuntimeException("sftp失败", e);
        }finally {
            returnChannelSftp(channelSftp);
        }
    }

    @Override
    public void delete(String path, String fileName) {
        ChannelSftp channelSftp=borrow();
        try {
            delete(channelSftp,path,fileName);
        } catch (Exception e) {
            throw new RuntimeException("sftp失败", e);
        }finally {
            returnChannelSftp(channelSftp);
        }
    }

    public void deleteDir(String path) {
        ChannelSftp channelSftp=borrow();
        try {
            deleteDir(channelSftp,path);
        } catch (Exception e) {
            throw new RuntimeException("sftp失败", e);
        }finally {
            returnChannelSftp(channelSftp);
        }
    }

    public void upload(ChannelSftp channelSftp,String path, String sftpFileName, InputStream input) throws SftpException{
        Map returnMap = boxDirectory(path, sftpFileName);
        String directory=CastUtil.castString(returnMap.get("directory"));
        sftpFileName=CastUtil.castString(returnMap.get("sftpFileName"));
        try{
            if(!isExist(channelSftp,directory,true)) {
                levelCreateDir(channelSftp,directory);
            }
            else{
                channelSftp.cd(directory);
            }
        }catch (SftpException e){
            levelCreateDir(channelSftp,directory);
        }
        channelSftp.put(input, sftpFileName);
    }

    public void upload(ChannelSftp channelSftp,String path, String sftpFileName, byte[] bytes){
        try {
            upload(channelSftp,path, sftpFileName, new ByteArrayInputStream(bytes));
        }catch (SftpException e){
            throw new RuntimeException("channel操作失败"+channelSftp, e);
        }
    }

    public Map boxDirectory(String directory, String sftpFileName) {
        Map returnMap = new HashMap();
        if (sftpFileName.contains("/")) {
            directory=directory+"/"+StringUtils.substringBeforeLast(sftpFileName,"/");
            sftpFileName= StringUtils.substringAfterLast(sftpFileName,"/");
        }
        returnMap.put("directory", directory);
        returnMap.put("sftpFileName", sftpFileName);
        return returnMap;
    }

    public InputStream downloadStream(ChannelSftp channelSftp,String path, String downloadFile){
        try {
            channelSftp.cd(initDir);
            return channelSftp.get(path + "/" + downloadFile);
        }catch (SftpException e){
            throw new RuntimeException("channel操作失败"+channelSftp, e);
        }
    }

    public void delete(ChannelSftp channelSftp,String path, String deleteFileName){
        try {
            channelSftp.cd(initDir);
            channelSftp.rm(path + "/" + deleteFileName);
        }catch (SftpException e){
            throw new RuntimeException("channel操作失败"+channelSftp, e);
        }
    }

    public boolean createDir(ChannelSftp channelSftp,String path) {
        try {
            if (isExist(channelSftp,path, true)) {
                return true;
            }
            levelCreateDir(channelSftp,path);
        } catch (SftpException e) {
            return false;
        }
        return true;
    }

    public void deleteDir(ChannelSftp channelSftp,String directory) throws SftpException {
        Vector vector = listFiles(channelSftp,directory);
        if(CollUtil.isEmpty(vector)){
            channelSftp.rmdir(directory);
        }
    }

    public Vector<?> listFiles(ChannelSftp channelSftp,String directory){
        try{
            if(isExist(channelSftp,directory,true)){
                Vector<?> vector =  channelSftp.ls(directory);
                //移除上级目录和根目录:"." ".."
                vector.remove(0);
                vector.remove(0);
                return vector;
            }
        }catch (SftpException e){
            throw new RuntimeException("channel操作失败"+channelSftp, e);
        }
        return null;
    }

    public void levelCreateDir(ChannelSftp channelSftp,String pathStr) throws SftpException {
        channelSftp.cd(initDir);
        String pathArry[] = pathStr.split("/");
        for (String path : pathArry) {
            if (path.equals("")) {
                continue;
            }
            if (isExist(channelSftp,path + "/", false)) {
                channelSftp.cd(path);
            } else {
                channelSftp.mkdir(path);
                channelSftp.cd(path);
            }
        }
    }

    public boolean isExist(ChannelSftp channelSftp,String pathStr, boolean gotoOpen) throws SftpException {
        boolean isExistFlag = false;
        if (gotoOpen) {
            channelSftp.cd(initDir);
        }
        try {
            channelSftp.lstat(pathStr);
            isExistFlag = true;
        } catch (Exception e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isExistFlag = false;
            }
        }
        return isExistFlag;
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值