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" + * 例如: + * * * @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); + } + + /** + * 移动文件或目录内容到目标目录中,例如: + * + * + * @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)); } /**