diff --git a/CHANGELOG.md b/CHANGELOG.md
index ffd48cb12..0da685e96 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,9 +3,12 @@
-------------------------------------------------------------------------------------------------------------
-# 5.7.9 (2021-08-12)
+# 5.7.9 (2021-08-16)
### 🐣新特性
+* 【extra 】 FileUtil增加moveContent方法(issue#I45H30@Gitee)
+* 【extra 】 JschPool.getSession获取时检查是否连接状态(issue#I45N5I@Gitee)
+*
### 🐞Bug修复
* 【extra 】 修复TinyPinyinEngine空构造造成可能的误判问题
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java
index 5364fff0e..d36c60eec 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java
@@ -1004,6 +1004,22 @@ public class FileUtil extends PathUtil {
move(src.toPath(), target.toPath(), isOverride);
}
+ /**
+ * 移动文件或者目录
+ *
+ * @param src 源文件或者目录
+ * @param target 目标文件或者目录
+ * @param isOverride 是否覆盖目标,只有目标为文件才覆盖
+ * @throws IORuntimeException IO异常
+ * @see PathUtil#moveContent(Path, Path, boolean)
+ * @since 5.7.9
+ */
+ public static void moveContent(File src, File target, boolean isOverride) throws IORuntimeException {
+ Assert.notNull(src, "Src file must be not null!");
+ Assert.notNull(target, "target file must be not null!");
+ moveContent(src.toPath(), target.toPath(), isOverride);
+ }
+
/**
* 修改文件或目录的文件名,不变更路径,只是简单修改文件名,不保留扩展名。
*
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java
index af1e878e4..c0ed49a2f 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java
@@ -210,6 +210,9 @@ public class PathUtil {
* @since 5.5.1
*/
public static Path copy(Path src, Path target, CopyOption... options) throws IORuntimeException {
+ Assert.notNull(src, "Src path must be not null !");
+ Assert.notNull(target, "Target path must be not null !");
+
if (isDirectory(src)) {
return copyContent(src, target.resolve(src.getFileName()), options);
}
@@ -231,6 +234,9 @@ public class PathUtil {
* @since 5.5.1
*/
public static Path copyContent(Path src, Path target, CopyOption... options) throws IORuntimeException {
+ Assert.notNull(src, "Src path must be not null !");
+ Assert.notNull(target, "Target path must be not null !");
+
try {
Files.walkFileTree(src, new CopyVisitor(src, target, options));
} catch (IOException e) {
@@ -452,7 +458,11 @@ public class PathUtil {
/**
* 移动文件或目录
* 当目标是目录时,会将源文件或文件夹整体移动至目标目录下
- * 例如:move("/usr/aaa", "/usr/bbb")结果为:"/usr/bbb/aaa"
+ * 例如:
+ *
+ * - move("/usr/aaa/abc.txt", "/usr/bbb")结果为:"/usr/bbb/abc.txt"
+ * - move("/usr/aaa", "/usr/bbb")结果为:"/usr/bbb/aaa"
+ *
*
* @param src 源文件或目录路径
* @param target 目标路径,如果为目录,则移动到此目录下
@@ -463,10 +473,31 @@ public class PathUtil {
public static Path move(Path src, Path target, boolean isOverride) {
Assert.notNull(src, "Src path must be not null !");
Assert.notNull(target, "Target path must be not null !");
- final CopyOption[] options = isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{};
+
if (isDirectory(target)) {
target = target.resolve(src.getFileName());
}
+ return moveContent(src, target, isOverride);
+ }
+
+ /**
+ * 移动文件或目录内容到目标目录中,例如:
+ *
+ * - moveContent("/usr/aaa/abc.txt", "/usr/bbb")结果为:"/usr/bbb/abc.txt"
+ * - moveContent("/usr/aaa", "/usr/bbb")结果为:"/usr/bbb"
+ *
+ *
+ * @param src 源文件或目录路径
+ * @param target 目标路径,如果为目录,则移动到此目录下
+ * @param isOverride 是否覆盖目标文件
+ * @return 目标文件Path
+ * @since 5.7.9
+ */
+ public static Path moveContent(Path src, Path target, boolean isOverride) {
+ Assert.notNull(src, "Src path must be not null !");
+ Assert.notNull(target, "Target path must be not null !");
+ final CopyOption[] options = isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{};
+
// 自动创建目标的父目录
mkParentDirs(target);
try {
diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/SimpleCache.java b/hutool-core/src/main/java/cn/hutool/core/lang/SimpleCache.java
index fcb407231..35352451e 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/SimpleCache.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/SimpleCache.java
@@ -10,6 +10,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Predicate;
/**
* 简单缓存,无超时实现,默认使用{@link WeakHashMap}实现缓存自动清理
@@ -76,15 +77,28 @@ public class SimpleCache implements Iterable>, Serializabl
* @return 值对象
*/
public V get(K key, Func0 supplier) {
+ return get(key, null, supplier);
+ }
+
+ /**
+ * 从缓存中获得对象,当对象不在缓存中或已经过期返回Func0回调产生的对象
+ *
+ * @param key 键
+ * @param validPredicate 检查结果对象是否可用,如是否断开连接等
+ * @param supplier 如果不存在回调方法或结果不可用,用于生产值对象
+ * @return 值对象
+ * @since 5.7.9
+ */
+ public V get(K key, Predicate validPredicate, Func0 supplier) {
V v = get(key);
- if(null == v && null != supplier){
+ if (null == v && null != supplier) {
//每个key单独获取一把锁,降低锁的粒度提高并发能力,see pr#1385@Github
final Lock keyLock = keyLockMap.computeIfAbsent(key, k -> new ReentrantLock());
keyLock.lock();
try {
// 双重检查,防止在竞争锁的过程中已经有其它线程写入
v = cache.get(key);
- if (null == v) {
+ if (null == v || (null != validPredicate && false == validPredicate.test(v))) {
try {
v = supplier.call();
} catch (Exception e) {
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ssh/JschSessionPool.java b/hutool-extra/src/main/java/cn/hutool/extra/ssh/JschSessionPool.java
index af8b99ae2..164b7824f 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/ssh/JschSessionPool.java
+++ b/hutool-extra/src/main/java/cn/hutool/extra/ssh/JschSessionPool.java
@@ -42,7 +42,7 @@ public enum JschSessionPool {
*/
public Session getSession(String sshHost, int sshPort, String sshUser, String sshPass) {
final String key = StrUtil.format("{}@{}:{}", sshUser, sshHost, sshPort);
- return this.cache.get(key, ()-> JschUtil.openSession(sshHost, sshPort, sshUser, sshPass));
+ return this.cache.get(key, Session::isConnected, ()-> JschUtil.openSession(sshHost, sshPort, sshUser, sshPass));
}
/**
@@ -57,7 +57,7 @@ public enum JschSessionPool {
*/
public Session getSession(String sshHost, int sshPort, String sshUser, String prvkey, byte[] passphrase) {
final String key = StrUtil.format("{}@{}:{}", sshUser, sshHost, sshPort);
- return this.cache.get(key, ()->JschUtil.openSession(sshHost, sshPort, sshUser, prvkey, passphrase));
+ return this.cache.get(key, Session::isConnected, ()->JschUtil.openSession(sshHost, sshPort, sshUser, prvkey, passphrase));
}
/**