记录一下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;
}
}