mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add session
This commit is contained in:
parent
8d7b890b3e
commit
8a0e477f69
@ -21,6 +21,7 @@ import org.dromara.hutool.core.map.WeakConcurrentMap;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
@ -28,6 +29,7 @@ import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 简单缓存,无超时实现,默认使用{@link WeakConcurrentMap}实现缓存自动清理
|
||||
@ -212,4 +214,13 @@ public class SimpleCache<K, V> implements Iterable<Map.Entry<K, V>>, Serializabl
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有键
|
||||
*
|
||||
* @return 所有键
|
||||
*/
|
||||
public List<K> keys(){
|
||||
return this.rawMap.keySet().stream().map(Mutable::get).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ package org.dromara.hutool.core.spi;
|
||||
|
||||
import org.dromara.hutool.core.cache.SimpleCache;
|
||||
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
|
||||
import org.dromara.hutool.core.collection.ListUtil;
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
import org.dromara.hutool.core.io.resource.MultiResource;
|
||||
import org.dromara.hutool.core.io.resource.Resource;
|
||||
@ -24,10 +25,7 @@ import org.dromara.hutool.core.text.StrUtil;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 列表类型的服务加载器,用于替换JDK提供的{@link java.util.ServiceLoader}<br>
|
||||
@ -136,6 +134,11 @@ public class ListServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
return this.serviceNames.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServiceNames(){
|
||||
return ListUtil.view(this.serviceNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定服务的实现类
|
||||
*
|
||||
@ -148,7 +151,12 @@ public class ListServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ClassLoaderUtil.loadClass(serviceClassName);
|
||||
return getServiceClass(serviceClassName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<S> getServiceClass(final String serviceName) {
|
||||
return ClassLoaderUtil.loadClass(serviceName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -162,7 +170,12 @@ public class ListServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
if (null == serviceClassName) {
|
||||
return null;
|
||||
}
|
||||
return getServiceByName(serviceClassName);
|
||||
return getService(serviceClassName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public S getService(final String serviceName) {
|
||||
return this.serviceCache.get(serviceName, () -> createService(serviceName));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -177,7 +190,7 @@ public class ListServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
|
||||
@Override
|
||||
public S next() {
|
||||
return getServiceByName(nameIter.next());
|
||||
return getService(nameIter.next());
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -223,7 +236,7 @@ public class ListServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
line = line.substring(0, ci);
|
||||
}
|
||||
line = StrUtil.trim(line);
|
||||
if (line.length() > 0) {
|
||||
if (!line.isEmpty()) {
|
||||
// 检查行
|
||||
checkLine(resource, lineNo, line);
|
||||
// 不覆盖模式
|
||||
@ -272,16 +285,6 @@ public class ListServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
throw new SPIException(this.serviceClass + ":" + resource.getUrl() + ":" + lineNo + ": " + msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定class名对应的服务,使用缓存,多次调用只返回相同的服务对象
|
||||
*
|
||||
* @param serviceClassName 服务名称
|
||||
* @return 服务对象
|
||||
*/
|
||||
private S getServiceByName(final String serviceClassName) {
|
||||
return this.serviceCache.get(serviceClassName, () -> createService(serviceClassName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建服务,无缓存
|
||||
*
|
||||
|
@ -14,6 +14,7 @@ package org.dromara.hutool.core.spi;
|
||||
|
||||
import org.dromara.hutool.core.cache.SimpleCache;
|
||||
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
|
||||
import org.dromara.hutool.core.collection.ListUtil;
|
||||
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
@ -21,6 +22,7 @@ import org.dromara.hutool.core.text.StrUtil;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@ -128,12 +130,12 @@ public class MapServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
return this.serviceProperties.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定服务的实现类
|
||||
*
|
||||
* @param serviceName 服务名称
|
||||
* @return 服务名称对应的实现类
|
||||
*/
|
||||
@Override
|
||||
public List<String> getServiceNames() {
|
||||
return ListUtil.view(this.serviceCache.keys());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<S> getServiceClass(final String serviceName) {
|
||||
final String serviceClassName = this.serviceProperties.getProperty(serviceName);
|
||||
if (StrUtil.isBlank(serviceClassName)) {
|
||||
@ -143,12 +145,7 @@ public class MapServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
return ClassLoaderUtil.loadClass(serviceClassName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定名称对应的服务,使用缓存,多次调用只返回相同的服务对象
|
||||
*
|
||||
* @param serviceName 服务名称
|
||||
* @return 服务对象
|
||||
*/
|
||||
@Override
|
||||
public S getService(final String serviceName) {
|
||||
return this.serviceCache.get(serviceName, () -> createService(serviceName));
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
package org.dromara.hutool.core.spi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* SPI服务加载接口<br>
|
||||
* 用户实现此接口用于制定不同的服务加载方式
|
||||
@ -19,7 +21,7 @@ package org.dromara.hutool.core.spi;
|
||||
* @param <S> 服务对象类型
|
||||
* @author looly
|
||||
*/
|
||||
public interface ServiceLoader<S> extends Iterable<S>{
|
||||
public interface ServiceLoader<S> extends Iterable<S> {
|
||||
|
||||
/**
|
||||
* 加载服务
|
||||
@ -32,4 +34,27 @@ public interface ServiceLoader<S> extends Iterable<S>{
|
||||
* @return 总数
|
||||
*/
|
||||
int size();
|
||||
|
||||
/**
|
||||
* 获取服务名称列表
|
||||
*
|
||||
* @return 服务名称列表
|
||||
*/
|
||||
List<String> getServiceNames();
|
||||
|
||||
/**
|
||||
* 获取指定服务的实现类
|
||||
*
|
||||
* @param serviceName 服务名称
|
||||
* @return 服务名称对应的实现类
|
||||
*/
|
||||
Class<S> getServiceClass(String serviceName);
|
||||
|
||||
/**
|
||||
* 获取指定名称对应的服务
|
||||
*
|
||||
* @param serviceName 服务名称
|
||||
* @return 服务对象
|
||||
*/
|
||||
S getService(String serviceName);
|
||||
}
|
||||
|
@ -25,6 +25,16 @@ import org.dromara.hutool.extra.pinyin.engine.PinyinEngineFactory;
|
||||
*/
|
||||
public class PinyinUtil {
|
||||
|
||||
/**
|
||||
* 创建拼音引擎
|
||||
*
|
||||
* @param engineName 引擎名称
|
||||
* @return {@link PinyinEngine}
|
||||
*/
|
||||
public static PinyinEngine createEngine(final String engineName) {
|
||||
return PinyinEngineFactory.createEngine(engineName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得全局单例的拼音引擎
|
||||
*
|
||||
|
@ -13,6 +13,7 @@
|
||||
package org.dromara.hutool.extra.pinyin.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.spi.ServiceLoader;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.extra.pinyin.PinyinException;
|
||||
@ -47,6 +48,26 @@ public class PinyinEngineFactory {
|
||||
return doCreateEngine();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建自定义引擎
|
||||
*
|
||||
* @param engineName 引擎名称,忽略大小写,如`Bopomofo4j`、`Houbb`、`JPinyin`、`Pinyin4j`、`TinyPinyin`
|
||||
* @return 引擎
|
||||
* @throws PinyinException 无对应名称的引擎
|
||||
*/
|
||||
public static PinyinEngine createEngine(String engineName) throws PinyinException {
|
||||
if (!StrUtil.endWithIgnoreCase(engineName, "Engine")) {
|
||||
engineName = engineName + "Engine";
|
||||
}
|
||||
final ServiceLoader<PinyinEngine> list = SpiUtil.loadList(PinyinEngine.class);
|
||||
for (final String serviceName : list.getServiceNames()) {
|
||||
if (StrUtil.endWithIgnoreCase(serviceName, engineName)) {
|
||||
return list.getService(serviceName);
|
||||
}
|
||||
}
|
||||
throw new PinyinException("No such engine named: " + engineName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户引入的拼音引擎jar,自动创建对应的拼音引擎对象<br>
|
||||
* 推荐创建的引擎单例使用,此方法每次调用会返回新的引擎
|
||||
|
@ -10,7 +10,7 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.pinyin.engine.houbbpinyin;
|
||||
package org.dromara.hutool.extra.pinyin.engine.houbb;
|
||||
|
||||
import org.dromara.hutool.extra.pinyin.engine.PinyinEngine;
|
||||
import com.github.houbb.pinyin.constant.enums.PinyinStyleEnum;
|
||||
@ -35,7 +35,7 @@ import com.github.houbb.pinyin.util.PinyinHelper;
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
public class HoubbPinyinEngine implements PinyinEngine {
|
||||
public class HoubbEngine implements PinyinEngine {
|
||||
|
||||
/**
|
||||
* 汉字拼音输出的格式
|
||||
@ -45,7 +45,7 @@ public class HoubbPinyinEngine implements PinyinEngine {
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public HoubbPinyinEngine() {
|
||||
public HoubbEngine() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ public class HoubbPinyinEngine implements PinyinEngine {
|
||||
*
|
||||
* @param format 格式
|
||||
*/
|
||||
public HoubbPinyinEngine(final PinyinStyleEnum format) {
|
||||
public HoubbEngine(final PinyinStyleEnum format) {
|
||||
init(format);
|
||||
}
|
||||
|
@ -29,4 +29,4 @@
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
package org.dromara.hutool.extra.pinyin.engine.houbbpinyin;
|
||||
package org.dromara.hutool.extra.pinyin.engine.houbb;
|
@ -15,13 +15,12 @@ package org.dromara.hutool.extra.ssh;
|
||||
/**
|
||||
* 连接者对象,提供一些连接的基本信息
|
||||
*
|
||||
* @author Luxiaolei
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
public class Connector {
|
||||
private String host;
|
||||
private int port;
|
||||
private String user;
|
||||
private String user = "root";
|
||||
private String password;
|
||||
private String group;
|
||||
|
||||
@ -34,9 +33,9 @@ public class Connector {
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param user 用户名
|
||||
* @param user 用户名
|
||||
* @param password 密码
|
||||
* @param group 组
|
||||
* @param group 组
|
||||
*/
|
||||
public Connector(final String user, final String password, final String group) {
|
||||
this.user = user;
|
||||
@ -47,9 +46,9 @@ public class Connector {
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param host 主机名
|
||||
* @param port 端口
|
||||
* @param user 用户名
|
||||
* @param host 主机名
|
||||
* @param port 端口
|
||||
* @param user 用户名
|
||||
* @param password 密码
|
||||
*/
|
||||
public Connector(final String host, final int port, final String user, final String password) {
|
||||
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
|
||||
import org.dromara.hutool.core.exception.ExceptionUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
/**
|
||||
* Jsch异常
|
||||
* @author xiaoleilu
|
||||
*/
|
||||
public class JschRuntimeException extends RuntimeException{
|
||||
private static final long serialVersionUID = 8247610319171014183L;
|
||||
|
||||
public JschRuntimeException(final Throwable e) {
|
||||
super(ExceptionUtil.getMessage(e), e);
|
||||
}
|
||||
|
||||
public JschRuntimeException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public JschRuntimeException(final String messageTemplate, final Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params));
|
||||
}
|
||||
|
||||
public JschRuntimeException(final String message, final Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
public JschRuntimeException(final String message, final Throwable throwable, final boolean enableSuppression, final boolean writableStackTrace) {
|
||||
super(message, throwable, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
public JschRuntimeException(final Throwable throwable, final String messageTemplate, final Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params), throwable);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
|
||||
import org.dromara.hutool.core.func.Wrapper;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
/**
|
||||
* SSH Session抽象
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
public interface Session extends Wrapper<Object>, Closeable {
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
|
||||
import org.dromara.hutool.core.exception.HutoolException;
|
||||
|
||||
/**
|
||||
* SSH异常
|
||||
*
|
||||
* @author xiaoleilu
|
||||
*/
|
||||
public class SshException extends HutoolException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param e 异常
|
||||
*/
|
||||
public SshException(final Throwable e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param message 消息
|
||||
*/
|
||||
public SshException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param messageTemplate 消息模板
|
||||
* @param params 参数
|
||||
*/
|
||||
public SshException(final String messageTemplate, final Object... params) {
|
||||
super(messageTemplate, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param message 消息
|
||||
* @param cause 被包装的子异常
|
||||
*/
|
||||
public SshException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param message 消息
|
||||
* @param cause 被包装的子异常
|
||||
* @param enableSuppression 是否启用抑制
|
||||
* @param writableStackTrace 堆栈跟踪是否应该是可写的
|
||||
*/
|
||||
public SshException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param cause 被包装的子异常
|
||||
* @param messageTemplate 消息模板
|
||||
* @param params 参数
|
||||
*/
|
||||
public SshException(final Throwable cause, final String messageTemplate, final Object... params) {
|
||||
super(cause, messageTemplate, params);
|
||||
}
|
||||
}
|
@ -10,65 +10,55 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
package org.dromara.hutool.extra.ssh.engine.ganymed;
|
||||
|
||||
import ch.ethz.ssh2.Connection;
|
||||
import ch.ethz.ssh2.Session;
|
||||
import ch.ethz.ssh2.StreamGobbler;
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.extra.ssh.Connector;
|
||||
import org.dromara.hutool.extra.ssh.Session;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Ganymed-SSH2封装,见:https://www.ganymed.ethz.ch/ssh2/
|
||||
* {@link ch.ethz.ssh2.Session}包装
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.5.3
|
||||
*/
|
||||
public class GanymedUtil {
|
||||
public class GanymedSession implements Session {
|
||||
|
||||
private final ch.ethz.ssh2.Session raw;
|
||||
|
||||
/**
|
||||
* 连接到服务器
|
||||
* 构造
|
||||
*
|
||||
* @param sshHost 主机
|
||||
* @param sshPort 端口
|
||||
* @return {@link Connection}
|
||||
* @param connector {@link Connector},保存连接和验证信息等
|
||||
*/
|
||||
public static Connection connect(final String sshHost, final int sshPort) {
|
||||
final Connection conn = new Connection(sshHost, sshPort);
|
||||
try {
|
||||
conn.connect();
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
return conn;
|
||||
public GanymedSession(final Connector connector) {
|
||||
this(openSession(connector));
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开远程会话
|
||||
* 构造
|
||||
*
|
||||
* @param sshHost 主机
|
||||
* @param sshPort 端口
|
||||
* @param sshUser 用户名,如果为null,默认root
|
||||
* @param sshPass 密码
|
||||
* @return {@link Session}
|
||||
* @param raw {@link ch.ethz.ssh2.Session}
|
||||
*/
|
||||
public static Session openSession(final String sshHost, final int sshPort, String sshUser, final String sshPass) {
|
||||
// 默认root用户
|
||||
if (StrUtil.isEmpty(sshUser)) {
|
||||
sshUser = "root";
|
||||
}
|
||||
public GanymedSession(final ch.ethz.ssh2.Session raw) {
|
||||
this.raw = raw;
|
||||
}
|
||||
|
||||
final Connection connect = connect(sshHost, sshPort);
|
||||
try {
|
||||
connect.authenticateWithPassword(sshUser, sshPass);
|
||||
return connect.openSession();
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
@Override
|
||||
public ch.ethz.ssh2.Session getRaw() {
|
||||
return raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (raw != null) {
|
||||
raw.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,24 +68,21 @@ public class GanymedUtil {
|
||||
* 此方法单次发送一个命令到服务端,不读取环境变量,执行结束后自动关闭Session,不会产生阻塞。
|
||||
* </p>
|
||||
*
|
||||
* @param session Session会话
|
||||
* @param cmd 命令
|
||||
* @param charset 发送和读取内容的编码
|
||||
* @param errStream 错误信息输出到的位置
|
||||
* @return 执行返回结果
|
||||
*/
|
||||
public static String exec(final Session session, final String cmd, final Charset charset, final OutputStream errStream) {
|
||||
public String exec(final String cmd, final Charset charset, final OutputStream errStream) {
|
||||
final String result;
|
||||
try {
|
||||
session.execCommand(cmd, charset.name());
|
||||
result = IoUtil.read(new StreamGobbler(session.getStdout()), charset);
|
||||
this.raw.execCommand(cmd, charset.name());
|
||||
result = IoUtil.read(new StreamGobbler(this.raw.getStdout()), charset);
|
||||
|
||||
// 错误输出
|
||||
IoUtil.copy(new StreamGobbler(session.getStderr()), errStream);
|
||||
IoUtil.copy(new StreamGobbler(this.raw.getStderr()), errStream);
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} finally {
|
||||
close(session);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -106,39 +93,50 @@ public class GanymedUtil {
|
||||
* 此方法单次发送一个命令到服务端,自动读取环境变量,执行结束后自动关闭Session,可能产生阻塞。
|
||||
* </p>
|
||||
*
|
||||
* @param session Session会话
|
||||
* @param cmd 命令
|
||||
* @param charset 发送和读取内容的编码
|
||||
* @param errStream 错误信息输出到的位置
|
||||
* @return 执行返回结果
|
||||
*/
|
||||
public static String execByShell(final Session session, final String cmd, final Charset charset, final OutputStream errStream) {
|
||||
public String execByShell(final String cmd, final Charset charset, final OutputStream errStream) {
|
||||
final String result;
|
||||
try {
|
||||
session.requestDumbPTY();
|
||||
IoUtil.write(session.getStdin(), charset, true, cmd);
|
||||
this.raw.requestDumbPTY();
|
||||
IoUtil.write(this.raw.getStdin(), charset, true, cmd);
|
||||
|
||||
result = IoUtil.read(new StreamGobbler(session.getStdout()), charset);
|
||||
result = IoUtil.read(new StreamGobbler(this.raw.getStdout()), charset);
|
||||
if(null != errStream){
|
||||
// 错误输出
|
||||
IoUtil.copy(new StreamGobbler(session.getStderr()), errStream);
|
||||
IoUtil.copy(new StreamGobbler(this.raw.getStderr()), errStream);
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} finally {
|
||||
close(session);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭会话
|
||||
* 初始化并打开新的Session
|
||||
*
|
||||
* @param session 会话通道
|
||||
* @param connector {@link Connector},保存连接和验证信息等
|
||||
* @return {@link ch.ethz.ssh2.Session}
|
||||
*/
|
||||
public static void close(final Session session) {
|
||||
if (session != null) {
|
||||
session.close();
|
||||
private static ch.ethz.ssh2.Session openSession(final Connector connector) {
|
||||
|
||||
// 建立连接
|
||||
final Connection conn = new Connection(connector.getHost(), connector.getPort());
|
||||
try {
|
||||
conn.connect();
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
|
||||
// 打开会话
|
||||
try {
|
||||
conn.authenticateWithPassword(connector.getUser(), connector.getPassword());
|
||||
return conn.openSession();
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
package org.dromara.hutool.extra.ssh.engine.jsch;
|
||||
|
||||
/**
|
||||
* Jsch支持的Channel类型
|
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.ssh.engine.jsch;
|
||||
|
||||
import com.jcraft.jsch.*;
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.util.ByteUtil;
|
||||
import org.dromara.hutool.core.util.CharsetUtil;
|
||||
import org.dromara.hutool.extra.ssh.Connector;
|
||||
import org.dromara.hutool.extra.ssh.Session;
|
||||
import org.dromara.hutool.extra.ssh.SshException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Jsch Session封装
|
||||
*/
|
||||
public class JschSession implements Session {
|
||||
|
||||
private final com.jcraft.jsch.Session raw;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param connector {@link Connector},保存连接和验证信息等
|
||||
*/
|
||||
public JschSession(final Connector connector) {
|
||||
this(openSession(connector));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param raw {@link com.jcraft.jsch.Session}
|
||||
*/
|
||||
public JschSession(final com.jcraft.jsch.Session raw) {
|
||||
this.raw = raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRaw() {
|
||||
return raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (raw != null && raw.isConnected()) {
|
||||
raw.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定端口到本地。 一个会话可绑定多个端口
|
||||
*
|
||||
* @param remoteHost 远程主机
|
||||
* @param remotePort 远程端口
|
||||
* @param localHost 本地主机
|
||||
* @param localPort 本地端口
|
||||
* @return 成功与否
|
||||
* @throws SshException 端口绑定失败异常
|
||||
*/
|
||||
public boolean bindPort(final String remoteHost, final int remotePort, final String localHost, final int localPort) throws SshException {
|
||||
if (this.raw != null && this.raw.isConnected()) {
|
||||
try {
|
||||
this.raw.setPortForwardingL(localHost, localPort, remoteHost, remotePort);
|
||||
} catch (final JSchException e) {
|
||||
throw new SshException(e, "From [{}:{}] mapping to [{}:{}] error!", remoteHost, remotePort, localHost, localPort);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定ssh服务端的serverPort端口, 到host主机的port端口上. <br>
|
||||
* 即数据从ssh服务端的serverPort端口, 流经ssh客户端, 达到host:port上.
|
||||
*
|
||||
* @param bindPort ssh服务端上要被绑定的端口
|
||||
* @param host 转发到的host
|
||||
* @param port host上的端口
|
||||
* @return 成功与否
|
||||
* @throws SshException 端口绑定失败异常
|
||||
*/
|
||||
public boolean bindRemotePort(final int bindPort, final String host, final int port) throws SshException {
|
||||
if (this.raw != null && this.raw.isConnected()) {
|
||||
try {
|
||||
this.raw.setPortForwardingR(bindPort, host, port);
|
||||
} catch (final JSchException e) {
|
||||
throw new SshException(e, "From [{}] mapping to [{}] error!", bindPort, port);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除端口映射
|
||||
*
|
||||
* @param localPort 需要解除的本地端口
|
||||
*/
|
||||
public void unBindPort(final int localPort) {
|
||||
try {
|
||||
this.raw.delPortForwardingL(localPort);
|
||||
} catch (final JSchException e) {
|
||||
throw new SshException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Channel连接
|
||||
*
|
||||
* @param channelType 通道类型,可以是shell或sftp等,见{@link ChannelType}
|
||||
* @return {@link Channel}
|
||||
*/
|
||||
public Channel createChannel(final ChannelType channelType) {
|
||||
final Channel channel;
|
||||
try {
|
||||
if (!this.raw.isConnected()) {
|
||||
this.raw.connect();
|
||||
}
|
||||
channel = this.raw.openChannel(channelType.getValue());
|
||||
} catch (final JSchException e) {
|
||||
throw new SshException(e);
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开Shell连接
|
||||
*
|
||||
* @return {@link ChannelShell}
|
||||
*/
|
||||
public ChannelShell openShell() {
|
||||
return (ChannelShell) openChannel(ChannelType.SHELL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开Channel连接
|
||||
*
|
||||
* @param channelType 通道类型,可以是shell或sftp等,见{@link ChannelType}
|
||||
* @return {@link Channel}
|
||||
*/
|
||||
public Channel openChannel(final ChannelType channelType) {
|
||||
return openChannel(channelType, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开Channel连接
|
||||
*
|
||||
* @param channelType 通道类型,可以是shell或sftp等,见{@link ChannelType}
|
||||
* @param timeout 连接超时时长,单位毫秒
|
||||
* @return {@link Channel}
|
||||
*/
|
||||
public Channel openChannel(final ChannelType channelType, final int timeout) {
|
||||
final Channel channel = createChannel(channelType);
|
||||
try {
|
||||
channel.connect(Math.max(timeout, 0));
|
||||
} catch (final JSchException e) {
|
||||
throw new SshException(e);
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行Shell命令
|
||||
*
|
||||
* @param cmd 命令
|
||||
* @param charset 发送和读取内容的编码
|
||||
* @return {@link ChannelExec}
|
||||
*/
|
||||
public String exec(final String cmd, final Charset charset) {
|
||||
return exec(cmd, charset, System.err);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行Shell命令(使用EXEC方式)
|
||||
* <p>
|
||||
* 此方法单次发送一个命令到服务端,不读取环境变量,执行结束后自动关闭channel,不会产生阻塞。
|
||||
* </p>
|
||||
*
|
||||
* @param cmd 命令
|
||||
* @param charset 发送和读取内容的编码
|
||||
* @param errStream 错误信息输出到的位置
|
||||
* @return 执行结果内容
|
||||
* @since 4.3.1
|
||||
*/
|
||||
public String exec(final String cmd, Charset charset, final OutputStream errStream) {
|
||||
if (null == charset) {
|
||||
charset = CharsetUtil.UTF_8;
|
||||
}
|
||||
final ChannelExec channel = (ChannelExec) createChannel(ChannelType.EXEC);
|
||||
channel.setCommand(ByteUtil.toBytes(cmd, charset));
|
||||
channel.setInputStream(null);
|
||||
channel.setErrStream(errStream);
|
||||
InputStream in = null;
|
||||
try {
|
||||
channel.connect();
|
||||
in = channel.getInputStream();
|
||||
return IoUtil.read(in, charset);
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} catch (final JSchException e) {
|
||||
throw new SshException(e);
|
||||
} finally {
|
||||
IoUtil.closeQuietly(in);
|
||||
if (channel.isConnected()) {
|
||||
channel.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行Shell命令
|
||||
* <p>
|
||||
* 此方法单次发送一个命令到服务端,自动读取环境变量,执行结束后自动关闭channel,不会产生阻塞。
|
||||
* </p>
|
||||
*
|
||||
* @param cmd 命令
|
||||
* @param charset 发送和读取内容的编码
|
||||
* @return {@link ChannelExec}
|
||||
* @since 5.2.5
|
||||
*/
|
||||
public static String execByShell(final String cmd, final Charset charset) {
|
||||
final ChannelShell shell = openShell();
|
||||
// 开始连接
|
||||
shell.setPty(true);
|
||||
OutputStream out = null;
|
||||
InputStream in = null;
|
||||
try {
|
||||
out = shell.getOutputStream();
|
||||
in = shell.getInputStream();
|
||||
|
||||
out.write(ByteUtil.toBytes(cmd, charset));
|
||||
out.flush();
|
||||
|
||||
return IoUtil.read(in, charset);
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} finally {
|
||||
IoUtil.closeQuietly(out);
|
||||
IoUtil.closeQuietly(in);
|
||||
if (shell.isConnected()) {
|
||||
shell.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建{@link com.jcraft.jsch.Session}
|
||||
*
|
||||
* @param connector {@link Connector},保存连接和验证信息等
|
||||
* @return {@link com.jcraft.jsch.Session}
|
||||
*/
|
||||
private static com.jcraft.jsch.Session openSession(final Connector connector) {
|
||||
final JSch jsch = new JSch();
|
||||
final com.jcraft.jsch.Session session;
|
||||
try {
|
||||
session = jsch.getSession(connector.getUser(), connector.getHost(), connector.getPort());
|
||||
} catch (final JSchException e) {
|
||||
throw new SshException(e);
|
||||
}
|
||||
|
||||
session.setPassword(connector.getPassword());
|
||||
// 设置第一次登录的时候提示,可选值:(ask | yes | no)
|
||||
session.setConfig("StrictHostKeyChecking", "no");
|
||||
|
||||
return session;
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
package org.dromara.hutool.extra.ssh.engine.jsch;
|
||||
|
||||
import org.dromara.hutool.core.cache.SimpleCache;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
@ -10,8 +10,9 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
package org.dromara.hutool.extra.ssh.engine.jsch;
|
||||
|
||||
import com.jcraft.jsch.*;
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
@ -19,7 +20,8 @@ import org.dromara.hutool.core.net.LocalPortGenerator;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.ByteUtil;
|
||||
import org.dromara.hutool.core.util.CharsetUtil;
|
||||
import com.jcraft.jsch.*;
|
||||
import org.dromara.hutool.extra.ssh.Connector;
|
||||
import org.dromara.hutool.extra.ssh.SshException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -112,7 +114,7 @@ public class JschUtil {
|
||||
session.setTimeout(timeout);
|
||||
session.connect(timeout);
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
@ -132,7 +134,7 @@ public class JschUtil {
|
||||
try {
|
||||
session.connect();
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
@ -154,7 +156,7 @@ public class JschUtil {
|
||||
session.setTimeout(timeout);
|
||||
session.connect(timeout);
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
@ -198,7 +200,7 @@ public class JschUtil {
|
||||
try {
|
||||
jsch.addIdentity(privateKeyPath, passphrase);
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
|
||||
return createSession(jsch, sshHost, sshPort, sshUser);
|
||||
@ -231,7 +233,7 @@ public class JschUtil {
|
||||
try {
|
||||
session = jsch.getSession(sshUser, sshHost, sshPort);
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
|
||||
// 设置第一次登录的时候提示,可选值:(ask | yes | no)
|
||||
@ -248,9 +250,9 @@ public class JschUtil {
|
||||
* @param remotePort 远程端口
|
||||
* @param localPort 本地端口
|
||||
* @return 成功与否
|
||||
* @throws JschRuntimeException 端口绑定失败异常
|
||||
* @throws SshException 端口绑定失败异常
|
||||
*/
|
||||
public static boolean bindPort(final Session session, final String remoteHost, final int remotePort, final int localPort) throws JschRuntimeException {
|
||||
public static boolean bindPort(final Session session, final String remoteHost, final int remotePort, final int localPort) throws SshException {
|
||||
return bindPort(session, remoteHost, remotePort, "127.0.0.1", localPort);
|
||||
}
|
||||
|
||||
@ -263,15 +265,15 @@ public class JschUtil {
|
||||
* @param localHost 本地主机
|
||||
* @param localPort 本地端口
|
||||
* @return 成功与否
|
||||
* @throws JschRuntimeException 端口绑定失败异常
|
||||
* @throws SshException 端口绑定失败异常
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public static boolean bindPort(final Session session, final String remoteHost, final int remotePort, final String localHost, final int localPort) throws JschRuntimeException {
|
||||
public static boolean bindPort(final Session session, final String remoteHost, final int remotePort, final String localHost, final int localPort) throws SshException {
|
||||
if (session != null && session.isConnected()) {
|
||||
try {
|
||||
session.setPortForwardingL(localHost, localPort, remoteHost, remotePort);
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e, "From [{}:{}] mapping to [{}:{}] error!", remoteHost, remotePort, localHost, localPort);
|
||||
throw new SshException(e, "From [{}:{}] mapping to [{}:{}] error!", remoteHost, remotePort, localHost, localPort);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -288,15 +290,15 @@ public class JschUtil {
|
||||
* @param host 转发到的host
|
||||
* @param port host上的端口
|
||||
* @return 成功与否
|
||||
* @throws JschRuntimeException 端口绑定失败异常
|
||||
* @throws SshException 端口绑定失败异常
|
||||
* @since 5.4.2
|
||||
*/
|
||||
public static boolean bindRemotePort(final Session session, final int bindPort, final String host, final int port) throws JschRuntimeException {
|
||||
public static boolean bindRemotePort(final Session session, final int bindPort, final String host, final int port) throws SshException {
|
||||
if (session != null && session.isConnected()) {
|
||||
try {
|
||||
session.setPortForwardingR(bindPort, host, port);
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e, "From [{}] mapping to [{}] error!", bindPort, port);
|
||||
throw new SshException(e, "From [{}] mapping to [{}] error!", bindPort, port);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -314,7 +316,7 @@ public class JschUtil {
|
||||
try {
|
||||
session.delPortForwardingL(localPort);
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,9 +327,9 @@ public class JschUtil {
|
||||
* @param remoteHost 远程主机
|
||||
* @param remotePort 远程端口
|
||||
* @return 映射后的本地端口
|
||||
* @throws JschRuntimeException 连接异常
|
||||
* @throws SshException 连接异常
|
||||
*/
|
||||
public static int openAndBindPortToLocal(final Connector sshConn, final String remoteHost, final int remotePort) throws JschRuntimeException {
|
||||
public static int openAndBindPortToLocal(final Connector sshConn, final String remoteHost, final int remotePort) throws SshException {
|
||||
final Session session = openSession(sshConn.getHost(), sshConn.getPort(), sshConn.getUser(), sshConn.getPassword());
|
||||
final int localPort = generateLocalPort();
|
||||
bindPort(session, remoteHost, remotePort, localPort);
|
||||
@ -419,7 +421,7 @@ public class JschUtil {
|
||||
try {
|
||||
channel.connect(Math.max(timeout, 0));
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
@ -440,7 +442,7 @@ public class JschUtil {
|
||||
}
|
||||
channel = session.openChannel(channelType.getValue());
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
@ -487,7 +489,7 @@ public class JschUtil {
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} catch (final JSchException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
} finally {
|
||||
IoUtil.closeQuietly(in);
|
||||
close(channel);
|
@ -10,7 +10,7 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
package org.dromara.hutool.extra.ssh.engine.jsch;
|
||||
|
||||
import org.dromara.hutool.core.collection.CollUtil;
|
||||
import org.dromara.hutool.core.collection.ListUtil;
|
||||
@ -26,6 +26,7 @@ import com.jcraft.jsch.Session;
|
||||
import com.jcraft.jsch.SftpATTRS;
|
||||
import com.jcraft.jsch.SftpException;
|
||||
import com.jcraft.jsch.SftpProgressMonitor;
|
||||
import org.dromara.hutool.extra.ssh.SshException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
@ -219,7 +220,7 @@ public class Sftp extends AbstractFtp {
|
||||
try {
|
||||
channel.setFilenameEncoding(charset.toString());
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
this.channel = channel;
|
||||
}
|
||||
@ -261,7 +262,7 @@ public class Sftp extends AbstractFtp {
|
||||
try {
|
||||
return getClient().pwd();
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,7 +276,7 @@ public class Sftp extends AbstractFtp {
|
||||
try {
|
||||
return getClient().getHome();
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,7 +366,7 @@ public class Sftp extends AbstractFtp {
|
||||
});
|
||||
} catch (final SftpException e) {
|
||||
if (!StrUtil.startWithIgnoreCase(e.getMessage(), "No such file")) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
// 文件不存在忽略
|
||||
}
|
||||
@ -382,7 +383,7 @@ public class Sftp extends AbstractFtp {
|
||||
getClient().mkdir(dir);
|
||||
return true;
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,7 +436,7 @@ public class Sftp extends AbstractFtp {
|
||||
try {
|
||||
getClient().rm(filePath);
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -459,7 +460,7 @@ public class Sftp extends AbstractFtp {
|
||||
try {
|
||||
list = channel.ls(channel.pwd());
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
|
||||
String fileName;
|
||||
@ -483,7 +484,7 @@ public class Sftp extends AbstractFtp {
|
||||
channel.rmdir(dirPath);
|
||||
return true;
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -583,7 +584,7 @@ public class Sftp extends AbstractFtp {
|
||||
try {
|
||||
getClient().put(srcFilePath, destPath, monitor, mode.ordinal());
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -602,7 +603,7 @@ public class Sftp extends AbstractFtp {
|
||||
try {
|
||||
getClient().put(srcStream, destPath, monitor, mode.ordinal());
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -630,7 +631,7 @@ public class Sftp extends AbstractFtp {
|
||||
* @param destDir 本地目录
|
||||
*/
|
||||
@Override
|
||||
public void recursiveDownloadFolder(final String sourcePath, final File destDir) throws JschRuntimeException {
|
||||
public void recursiveDownloadFolder(final String sourcePath, final File destDir) throws SshException {
|
||||
String fileName;
|
||||
String srcFile;
|
||||
File destFile;
|
||||
@ -665,7 +666,7 @@ public class Sftp extends AbstractFtp {
|
||||
try {
|
||||
getClient().get(src, dest);
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -682,7 +683,7 @@ public class Sftp extends AbstractFtp {
|
||||
try {
|
||||
getClient().get(src, out);
|
||||
} catch (final SftpException e) {
|
||||
throw new JschRuntimeException(e);
|
||||
throw new SshException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* SSH 引擎封装
|
||||
* Jsch(http://www.jcraft.com/jsch/) 引擎封装
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
|
@ -10,7 +10,7 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
package org.dromara.hutool.extra.ssh.engine.sshj;
|
||||
|
||||
import org.dromara.hutool.core.collection.CollUtil;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
@ -41,4 +41,14 @@ public class TokenizerUtil {
|
||||
public static TokenizerEngine getEngine() {
|
||||
return TokenizerEngineFactory.getEngine();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建对应名称的分词引擎对象
|
||||
*
|
||||
* @param engineName 引擎名称
|
||||
* @return {@link TokenizerEngine}
|
||||
*/
|
||||
public static TokenizerEngine createEngine(final String engineName) {
|
||||
return TokenizerEngineFactory.createEngine(engineName);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
package org.dromara.hutool.extra.tokenizer.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.spi.ServiceLoader;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.extra.tokenizer.TokenizerException;
|
||||
@ -31,7 +32,7 @@ public class TokenizerEngineFactory {
|
||||
*
|
||||
* @return 单例的TokenizerEngine
|
||||
*/
|
||||
public static TokenizerEngine getEngine(){
|
||||
public static TokenizerEngine getEngine() {
|
||||
final TokenizerEngine engine = Singleton.get(TokenizerEngine.class.getName(), TokenizerEngineFactory::createEngine);
|
||||
LogUtil.debug("Use [{}] Tokenizer Engine As Default.", StrUtil.removeSuffix(engine.getClass().getSimpleName(), "Engine"));
|
||||
return engine;
|
||||
@ -46,6 +47,26 @@ public class TokenizerEngineFactory {
|
||||
return doCreateEngine();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建自定义引擎
|
||||
*
|
||||
* @param engineName 引擎名称,忽略大小写,如`Analysis`、`Ansj`、`HanLP`、`IKAnalyzer`、`Jcseg`、`Jieba`、`Mmseg`、`Mynlp`、`Word`
|
||||
* @return 引擎
|
||||
* @throws TokenizerException 无对应名称的引擎
|
||||
*/
|
||||
public static TokenizerEngine createEngine(String engineName) throws TokenizerException {
|
||||
if (!StrUtil.endWithIgnoreCase(engineName, "Engine")) {
|
||||
engineName = engineName + "Engine";
|
||||
}
|
||||
final ServiceLoader<TokenizerEngine> list = SpiUtil.loadList(TokenizerEngine.class);
|
||||
for (final String serviceName : list.getServiceNames()) {
|
||||
if (StrUtil.endWithIgnoreCase(serviceName, engineName)) {
|
||||
return list.getService(serviceName);
|
||||
}
|
||||
}
|
||||
throw new TokenizerException("No such engine named: " + engineName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户引入的分词引擎jar,自动创建对应的分词引擎对象
|
||||
*
|
||||
@ -53,7 +74,7 @@ public class TokenizerEngineFactory {
|
||||
*/
|
||||
private static TokenizerEngine doCreateEngine() {
|
||||
final TokenizerEngine engine = SpiUtil.loadFirstAvailable(TokenizerEngine.class);
|
||||
if(null != engine){
|
||||
if (null != engine) {
|
||||
return engine;
|
||||
}
|
||||
|
||||
|
@ -14,4 +14,4 @@ org.dromara.hutool.extra.pinyin.engine.tinypinyin.TinyPinyinEngine
|
||||
org.dromara.hutool.extra.pinyin.engine.jpinyin.JPinyinEngine
|
||||
org.dromara.hutool.extra.pinyin.engine.pinyin4j.Pinyin4jEngine
|
||||
org.dromara.hutool.extra.pinyin.engine.bopomofo4j.Bopomofo4jEngine
|
||||
org.dromara.hutool.extra.pinyin.engine.houbbpinyin.HoubbPinyinEngine
|
||||
org.dromara.hutool.extra.pinyin.engine.houbb.HoubbEngine
|
||||
|
@ -16,7 +16,7 @@ import org.apache.commons.net.ftp.FTPSClient;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.io.file.FileUtil;
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.dromara.hutool.extra.ssh.Sftp;
|
||||
import org.dromara.hutool.extra.ssh.engine.jsch.Sftp;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -12,13 +12,13 @@
|
||||
|
||||
package org.dromara.hutool.extra.pinyin;
|
||||
|
||||
import org.dromara.hutool.extra.pinyin.engine.bopomofo4j.Bopomofo4jEngine;
|
||||
import org.dromara.hutool.extra.pinyin.engine.PinyinEngine;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class Bopomofo4jTest {
|
||||
|
||||
final Bopomofo4jEngine engine = new Bopomofo4jEngine();
|
||||
final PinyinEngine engine = PinyinUtil.createEngine("bopomofo4j");
|
||||
|
||||
@Test
|
||||
public void getFirstLetterByBopomofo4jTest(){
|
||||
|
@ -12,13 +12,13 @@
|
||||
|
||||
package org.dromara.hutool.extra.pinyin;
|
||||
|
||||
import org.dromara.hutool.extra.pinyin.engine.houbbpinyin.HoubbPinyinEngine;
|
||||
import org.dromara.hutool.extra.pinyin.engine.PinyinEngine;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class HoubbPinyinTest {
|
||||
|
||||
final HoubbPinyinEngine engine = new HoubbPinyinEngine();
|
||||
final PinyinEngine engine = PinyinUtil.createEngine("houbb");
|
||||
|
||||
@Test
|
||||
public void getFirstLetterTest(){
|
||||
|
@ -12,13 +12,13 @@
|
||||
|
||||
package org.dromara.hutool.extra.pinyin;
|
||||
|
||||
import org.dromara.hutool.extra.pinyin.engine.jpinyin.JPinyinEngine;
|
||||
import org.dromara.hutool.extra.pinyin.engine.PinyinEngine;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class JpinyinTest {
|
||||
|
||||
final JPinyinEngine engine = new JPinyinEngine();
|
||||
final PinyinEngine engine = PinyinUtil.createEngine("jpinyin");
|
||||
|
||||
@Test
|
||||
public void getFirstLetterByPinyin4jTest(){
|
||||
|
@ -12,13 +12,13 @@
|
||||
|
||||
package org.dromara.hutool.extra.pinyin;
|
||||
|
||||
import org.dromara.hutool.extra.pinyin.engine.pinyin4j.Pinyin4jEngine;
|
||||
import org.dromara.hutool.extra.pinyin.engine.PinyinEngine;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class Pinyin4jTest {
|
||||
|
||||
final Pinyin4jEngine engine = new Pinyin4jEngine();
|
||||
final PinyinEngine engine = PinyinUtil.createEngine("pinyin4j");
|
||||
|
||||
@Test
|
||||
public void getFirstLetterByPinyin4jTest(){
|
||||
|
@ -12,13 +12,13 @@
|
||||
|
||||
package org.dromara.hutool.extra.pinyin;
|
||||
|
||||
import org.dromara.hutool.extra.pinyin.engine.tinypinyin.TinyPinyinEngine;
|
||||
import org.dromara.hutool.extra.pinyin.engine.PinyinEngine;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class TinyPinyinTest {
|
||||
|
||||
final TinyPinyinEngine engine = new TinyPinyinEngine();
|
||||
final PinyinEngine engine = PinyinUtil.createEngine("tinypinyin");
|
||||
|
||||
@Test
|
||||
public void getFirstLetterByPinyin4jTest(){
|
||||
|
@ -15,6 +15,8 @@ package org.dromara.hutool.extra.ssh;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import com.jcraft.jsch.Session;
|
||||
import org.dromara.hutool.extra.ssh.engine.jsch.JschUtil;
|
||||
import org.dromara.hutool.extra.ssh.engine.jsch.Sftp;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -74,7 +76,7 @@ public class JschUtilTest {
|
||||
Console.log("isConnected " + sftp.getClient().isConnected());
|
||||
Console.log("打印pwd: " + sftp.pwd());
|
||||
Console.log("cd / : " + sftp.cd("/"));
|
||||
}catch (final JschRuntimeException e) {
|
||||
}catch (final SshException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
|
||||
import org.dromara.hutool.core.util.CharsetUtil;
|
||||
import org.dromara.hutool.extra.ssh.engine.sshj.SshjSftp;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -14,14 +14,6 @@ package org.dromara.hutool.extra.tokenizer;
|
||||
|
||||
import org.dromara.hutool.core.collection.iter.IterUtil;
|
||||
import org.dromara.hutool.extra.tokenizer.engine.TokenizerEngine;
|
||||
import org.dromara.hutool.extra.tokenizer.engine.analysis.SmartcnEngine;
|
||||
import org.dromara.hutool.extra.tokenizer.engine.hanlp.HanLPEngine;
|
||||
import org.dromara.hutool.extra.tokenizer.engine.ikanalyzer.IKAnalyzerEngine;
|
||||
import org.dromara.hutool.extra.tokenizer.engine.jcseg.JcsegEngine;
|
||||
import org.dromara.hutool.extra.tokenizer.engine.jieba.JiebaEngine;
|
||||
import org.dromara.hutool.extra.tokenizer.engine.mmseg.MmsegEngine;
|
||||
import org.dromara.hutool.extra.tokenizer.engine.mynlp.MynlpEngine;
|
||||
import org.dromara.hutool.extra.tokenizer.engine.word.WordEngine;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -51,7 +43,7 @@ public class TokenizerUtilTest {
|
||||
|
||||
@Test
|
||||
public void hanlpTest() {
|
||||
final TokenizerEngine engine = new HanLPEngine();
|
||||
final TokenizerEngine engine = TokenizerUtil.createEngine("hanlp");
|
||||
final Result result = engine.parse(text);
|
||||
final String resultStr = IterUtil.join(result, " ");
|
||||
Assertions.assertEquals("这 两 个 方法 的 区别 在于 返回 值", resultStr);
|
||||
@ -59,7 +51,7 @@ public class TokenizerUtilTest {
|
||||
|
||||
@Test
|
||||
public void ikAnalyzerTest() {
|
||||
final TokenizerEngine engine = new IKAnalyzerEngine();
|
||||
final TokenizerEngine engine = TokenizerUtil.createEngine("IKAnalyzer");
|
||||
final Result result = engine.parse(text);
|
||||
final String resultStr = IterUtil.join(result, " ");
|
||||
Assertions.assertEquals("这两个 方法 的 区别 在于 返回值", resultStr);
|
||||
@ -67,14 +59,14 @@ public class TokenizerUtilTest {
|
||||
|
||||
@Test
|
||||
public void jcsegTest() {
|
||||
final TokenizerEngine engine = new JcsegEngine();
|
||||
final TokenizerEngine engine = TokenizerUtil.createEngine("Jcseg");
|
||||
final Result result = engine.parse(text);
|
||||
checkResult(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jiebaTest() {
|
||||
final TokenizerEngine engine = new JiebaEngine();
|
||||
final TokenizerEngine engine = TokenizerUtil.createEngine("Jieba");
|
||||
final Result result = engine.parse(text);
|
||||
final String resultStr = IterUtil.join(result, " ");
|
||||
Assertions.assertEquals("这 两个 方法 的 区别 在于 返回值", resultStr);
|
||||
@ -82,14 +74,14 @@ public class TokenizerUtilTest {
|
||||
|
||||
@Test
|
||||
public void mmsegTest() {
|
||||
final TokenizerEngine engine = new MmsegEngine();
|
||||
final TokenizerEngine engine = TokenizerUtil.createEngine("Mmseg");
|
||||
final Result result = engine.parse(text);
|
||||
checkResult(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void smartcnTest() {
|
||||
final TokenizerEngine engine = new SmartcnEngine();
|
||||
final TokenizerEngine engine = TokenizerUtil.createEngine("Smartcn");
|
||||
final Result result = engine.parse(text);
|
||||
final String resultStr = IterUtil.join(result, " ");
|
||||
Assertions.assertEquals("这 两 个 方法 的 区别 在于 返回 值", resultStr);
|
||||
@ -97,7 +89,7 @@ public class TokenizerUtilTest {
|
||||
|
||||
@Test
|
||||
public void wordTest() {
|
||||
final TokenizerEngine engine = new WordEngine();
|
||||
final TokenizerEngine engine = TokenizerUtil.createEngine("Word");
|
||||
final Result result = engine.parse(text);
|
||||
final String resultStr = IterUtil.join(result, " ");
|
||||
Assertions.assertEquals("这两个 方法 的 区别 在于 返回值", resultStr);
|
||||
@ -105,7 +97,7 @@ public class TokenizerUtilTest {
|
||||
|
||||
@Test
|
||||
public void mynlpTest() {
|
||||
final TokenizerEngine engine = new MynlpEngine();
|
||||
final TokenizerEngine engine = TokenizerUtil.createEngine("Mynlp");
|
||||
final Result result = engine.parse(text);
|
||||
final String resultStr = IterUtil.join(result, " ");
|
||||
Assertions.assertEquals("这 两个 方法 的 区别 在于 返回 值", resultStr);
|
||||
|
@ -17,6 +17,7 @@ import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.http.client.ClientConfig;
|
||||
import org.dromara.hutool.http.client.Request;
|
||||
import org.dromara.hutool.http.client.Response;
|
||||
import org.dromara.hutool.http.client.engine.ClientEngine;
|
||||
import org.dromara.hutool.http.client.engine.ClientEngineFactory;
|
||||
import org.dromara.hutool.http.meta.Method;
|
||||
import org.dromara.hutool.http.server.SimpleServer;
|
||||
@ -85,8 +86,8 @@ public class HttpUtil {
|
||||
@SuppressWarnings("resource")
|
||||
public static String get(final String urlString, final int timeout) {
|
||||
return ClientEngineFactory.getEngine()
|
||||
.init(ClientConfig.of().setConnectionTimeout(timeout).setReadTimeout(timeout))
|
||||
.send(Request.of(urlString)).bodyStr();
|
||||
.init(ClientConfig.of().setConnectionTimeout(timeout).setReadTimeout(timeout))
|
||||
.send(Request.of(urlString)).bodyStr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,7 +100,7 @@ public class HttpUtil {
|
||||
@SuppressWarnings("resource")
|
||||
public static String get(final String urlString, final Map<String, Object> paramMap) {
|
||||
return send(Request.of(urlString).form(paramMap))
|
||||
.bodyStr();
|
||||
.bodyStr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +113,7 @@ public class HttpUtil {
|
||||
@SuppressWarnings("resource")
|
||||
public static String post(final String urlString, final Map<String, Object> paramMap) {
|
||||
return send(Request.of(urlString).method(Method.POST).form(paramMap))
|
||||
.bodyStr();
|
||||
.bodyStr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,7 +132,7 @@ public class HttpUtil {
|
||||
@SuppressWarnings("resource")
|
||||
public static String post(final String urlString, final String body) {
|
||||
return send(Request.of(urlString).method(Method.POST).body(body))
|
||||
.bodyStr();
|
||||
.bodyStr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,18 +141,18 @@ public class HttpUtil {
|
||||
* @param request HTTP请求
|
||||
* @return HTTP响应
|
||||
*/
|
||||
public static Response send(final Request request){
|
||||
public static Response send(final Request request) {
|
||||
return ClientEngineFactory.getEngine().send(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将表单数据加到URL中(用于GET表单提交)
|
||||
* 表单的键值对会被url编码,但是url中原参数不会被编码
|
||||
* 且对form参数进行 FormUrlEncoded ,x-www-form-urlencoded模式,此模式下空格会编码为'+'
|
||||
* 且对form参数进行 FormUrlEncoded ,x-www-form-urlencoded模式,此模式下空格会编码为'+'
|
||||
*
|
||||
* @param url URL
|
||||
* @param form 表单数据
|
||||
* @param charset 编码 null表示不encode键值对
|
||||
* @param url URL
|
||||
* @param form 表单数据
|
||||
* @param charset 编码 null表示不encode键值对
|
||||
* @return 合成后的URL
|
||||
*/
|
||||
public static String urlWithFormUrlEncoded(final String url, final Map<String, Object> form, final Charset charset) {
|
||||
@ -213,6 +214,16 @@ public class HttpUtil {
|
||||
return urlBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建客户端引擎
|
||||
*
|
||||
* @param engineName 引擎名称
|
||||
* @return {@link ClientEngine}
|
||||
*/
|
||||
public static ClientEngine createClient(final String engineName) {
|
||||
return ClientEngineFactory.createEngine(engineName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建简易的Http服务器
|
||||
*
|
||||
|
@ -13,6 +13,7 @@
|
||||
package org.dromara.hutool.http.client.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.spi.ServiceLoader;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.http.HttpException;
|
||||
@ -48,6 +49,26 @@ public class ClientEngineFactory {
|
||||
return createEngine().init(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建自定义引擎
|
||||
*
|
||||
* @param engineName 引擎名称,忽略大小写,如`HttpClient4`、`HttpClient5`、`OkHttp`、`JdkClient`
|
||||
* @return 引擎
|
||||
* @throws HttpException 无对应名称的引擎
|
||||
*/
|
||||
public static ClientEngine createEngine(String engineName) throws HttpException {
|
||||
if (!StrUtil.endWithIgnoreCase(engineName, "Engine")) {
|
||||
engineName = engineName + "Engine";
|
||||
}
|
||||
final ServiceLoader<ClientEngine> list = SpiUtil.loadList(ClientEngine.class);
|
||||
for (final String serviceName : list.getServiceNames()) {
|
||||
if (StrUtil.endWithIgnoreCase(serviceName, engineName)) {
|
||||
return list.getService(serviceName);
|
||||
}
|
||||
}
|
||||
throw new HttpException("No such engine named: " + engineName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户引入的HTTP客户端引擎jar,自动创建对应的拼音引擎对象<br>
|
||||
* 推荐创建的引擎单例使用,此方法每次调用会返回新的引擎
|
||||
|
@ -13,8 +13,8 @@
|
||||
package org.dromara.hutool.http.client;
|
||||
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.dromara.hutool.http.HttpUtil;
|
||||
import org.dromara.hutool.http.client.engine.ClientEngine;
|
||||
import org.dromara.hutool.http.client.engine.httpclient4.HttpClient4Engine;
|
||||
import org.dromara.hutool.http.meta.Method;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -25,7 +25,7 @@ public class HttpClient4EngineTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void getTest() {
|
||||
final ClientEngine engine = new HttpClient4Engine();
|
||||
final ClientEngine engine = HttpUtil.createClient("httpclient4");
|
||||
|
||||
final Request req = Request.of("https://www.hutool.cn/").method(Method.GET);
|
||||
final Response res = engine.send(req);
|
||||
|
@ -13,8 +13,8 @@
|
||||
package org.dromara.hutool.http.client;
|
||||
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.dromara.hutool.http.HttpUtil;
|
||||
import org.dromara.hutool.http.client.engine.ClientEngine;
|
||||
import org.dromara.hutool.http.client.engine.httpclient5.HttpClient5Engine;
|
||||
import org.dromara.hutool.http.meta.Method;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -25,7 +25,7 @@ public class HttpClient5EngineTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void getTest() {
|
||||
final ClientEngine engine = new HttpClient5Engine();
|
||||
final ClientEngine engine = HttpUtil.createClient("httpclient5");
|
||||
|
||||
final Request req = Request.of("https://www.hutool.cn/").method(Method.GET);
|
||||
final Response res = engine.send(req);
|
||||
|
@ -13,9 +13,8 @@
|
||||
package org.dromara.hutool.http.client;
|
||||
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.dromara.hutool.http.HttpUtil;
|
||||
import org.dromara.hutool.http.client.engine.ClientEngine;
|
||||
import org.dromara.hutool.http.client.engine.httpclient4.HttpClient4Engine;
|
||||
import org.dromara.hutool.http.client.engine.okhttp.OkHttpEngine;
|
||||
import org.dromara.hutool.http.meta.Method;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -25,7 +24,7 @@ public class Issue3240Test {
|
||||
@Disabled
|
||||
void okHttpTest() {
|
||||
String url = "https://gh.yubue.cn/https://github.com/espressif/arduino-esp32/releases/download/2.0.11/package_esp32_dev_index.json";
|
||||
final ClientEngine engine = new OkHttpEngine();
|
||||
final ClientEngine engine = HttpUtil.createClient("okhttp");
|
||||
final Response send = engine.send(Request.of(url).method(Method.GET));
|
||||
Console.log(send.body().getString());
|
||||
}
|
||||
@ -34,7 +33,7 @@ public class Issue3240Test {
|
||||
@Disabled
|
||||
void httpClient4Test() {
|
||||
String url = "https://gh.yubue.cn/https://github.com/espressif/arduino-esp32/releases/download/2.0.11/package_esp32_dev_index.json";
|
||||
final ClientEngine engine = new HttpClient4Engine();
|
||||
final ClientEngine engine = HttpUtil.createClient("okhttp");
|
||||
final Response send = engine.send(Request.of(url).method(Method.GET));
|
||||
Console.log(send.body().getString());
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
public class IssueI7ZRJUTest {
|
||||
|
||||
@SuppressWarnings({"resource", "TestFailedLine"})
|
||||
@SuppressWarnings({"resource"})
|
||||
@Test
|
||||
@Disabled
|
||||
void getBadSSlTest() {
|
||||
|
@ -13,8 +13,8 @@
|
||||
package org.dromara.hutool.http.client;
|
||||
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.dromara.hutool.http.HttpUtil;
|
||||
import org.dromara.hutool.http.client.engine.ClientEngine;
|
||||
import org.dromara.hutool.http.client.engine.jdk.JdkClientEngine;
|
||||
import org.dromara.hutool.http.meta.Method;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -24,7 +24,7 @@ public class JdkEngineTest {
|
||||
@Test
|
||||
@Disabled
|
||||
public void getTest(){
|
||||
final ClientEngine engine = new JdkClientEngine();
|
||||
final ClientEngine engine = HttpUtil.createClient("jdkClient");
|
||||
|
||||
final Request req = Request.of("https://www.hutool.cn/").method(Method.GET);
|
||||
final Response res = engine.send(req);
|
||||
|
Loading…
x
Reference in New Issue
Block a user