mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
03b8f57648
commit
91178e45a8
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.io.file;
|
package org.dromara.hutool.core.io.file;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
import org.dromara.hutool.core.io.IORuntimeException;
|
import org.dromara.hutool.core.io.IORuntimeException;
|
||||||
import org.dromara.hutool.core.io.IoUtil;
|
import org.dromara.hutool.core.io.IoUtil;
|
||||||
import org.dromara.hutool.core.util.CharsetUtil;
|
import org.dromara.hutool.core.util.CharsetUtil;
|
||||||
@ -32,6 +33,42 @@ import java.util.Set;
|
|||||||
* @since 5.4.1
|
* @since 5.4.1
|
||||||
*/
|
*/
|
||||||
public class PathUtil {
|
public class PathUtil {
|
||||||
|
/**
|
||||||
|
* 拼接多个路径
|
||||||
|
*
|
||||||
|
* @param firstPath 第一个路径
|
||||||
|
* @param paths 其它路径
|
||||||
|
* @return 拼接后的路径
|
||||||
|
* @see Paths#get(String, String...)
|
||||||
|
*/
|
||||||
|
public static Path of(final String firstPath, final String... paths) {
|
||||||
|
return Paths.get(firstPath, paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拼接多个路径,
|
||||||
|
*
|
||||||
|
* @param firstPath 第一个路径
|
||||||
|
* @param paths 其它路径
|
||||||
|
* @return 拼接后的路径
|
||||||
|
*/
|
||||||
|
public static Path of(Path firstPath, final Path... paths) {
|
||||||
|
if (ArrayUtil.isEmpty(paths)) {
|
||||||
|
return firstPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Path path : paths) {
|
||||||
|
if (null == path) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (null == firstPath) {
|
||||||
|
firstPath = path;
|
||||||
|
} else {
|
||||||
|
firstPath = firstPath.resolve(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return firstPath;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 目录是否为空
|
* 目录是否为空
|
||||||
@ -115,6 +152,7 @@ public class PathUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// region ----- walkFiles
|
// region ----- walkFiles
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 遍历指定path下的文件并做处理
|
* 遍历指定path下的文件并做处理
|
||||||
*
|
*
|
||||||
@ -580,7 +618,9 @@ public class PathUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将Path路径转换为标准的绝对路径
|
* 将Path路径转换为标准的绝对路径<br>
|
||||||
|
* 如果{@link Path#isAbsolute()}为{@code true},表示已经是绝对路径,返回本身<br>
|
||||||
|
* 如果是相对路径,则返回相对于系统默认目录的路径(一般为项目路径)
|
||||||
*
|
*
|
||||||
* @param path 文件或目录Path
|
* @param path 文件或目录Path
|
||||||
* @return 转换后的Path
|
* @return 转换后的Path
|
||||||
@ -594,7 +634,10 @@ public class PathUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取实际路径,路径文件必须存在
|
* 获取实际路径,路径文件必须存在<br>
|
||||||
|
* 如果给定Path是软链接(符号链接),则返回指向的实际链接<br>
|
||||||
|
* 如果路径不存在,会直接抛出NoSuchFileException异常<br>
|
||||||
|
* 无论给定是何种类型的路径,返回都是唯一的路径(总是equals)
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @return 实际路径
|
* @return 实际路径
|
||||||
|
@ -22,7 +22,6 @@ import java.io.Closeable;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.WatchEvent;
|
import java.nio.file.WatchEvent;
|
||||||
import java.nio.file.WatchService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 路径监听器
|
* 路径监听器
|
||||||
@ -61,7 +60,7 @@ public class WatchMonitor extends Thread implements Closeable, Serializable {
|
|||||||
* 构造
|
* 构造
|
||||||
*
|
*
|
||||||
* @param dir 字符串路径
|
* @param dir 字符串路径
|
||||||
* @param events 监听事件列表
|
* @param events 监听事件列表,如创建、修改和删除等
|
||||||
*/
|
*/
|
||||||
public WatchMonitor(final Path dir, final WatchEvent.Kind<?>... events) {
|
public WatchMonitor(final Path dir, final WatchEvent.Kind<?>... events) {
|
||||||
this(dir, 0, events);
|
this(dir, 0, events);
|
||||||
@ -78,10 +77,10 @@ public class WatchMonitor extends Thread implements Closeable, Serializable {
|
|||||||
*
|
*
|
||||||
* @param dir 路径
|
* @param dir 路径
|
||||||
* @param maxDepth 递归目录的最大深度,当小于2时不递归下层目录
|
* @param maxDepth 递归目录的最大深度,当小于2时不递归下层目录
|
||||||
* @param events 监听事件列表
|
* @param events 监听事件列表,如创建、修改和删除等
|
||||||
*/
|
*/
|
||||||
public WatchMonitor(final Path dir, final int maxDepth, final WatchEvent.Kind<?>... events) {
|
public WatchMonitor(final Path dir, final int maxDepth, final WatchEvent.Kind<?>... events) {
|
||||||
this.watchService = new WatchServiceWrapper().setEvents(events);
|
this.watchService = WatchServiceWrapper.of(events);
|
||||||
this.dir = dir;
|
this.dir = dir;
|
||||||
this.maxDepth = maxDepth;
|
this.maxDepth = maxDepth;
|
||||||
this.init();
|
this.init();
|
||||||
@ -161,7 +160,6 @@ public class WatchMonitor extends Thread implements Closeable, Serializable {
|
|||||||
* 初始化包括:
|
* 初始化包括:
|
||||||
* <pre>
|
* <pre>
|
||||||
* 1、解析传入的路径,判断其为目录还是文件
|
* 1、解析传入的路径,判断其为目录还是文件
|
||||||
* 2、创建{@link WatchService} 对象
|
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @throws WatchException 监听异常,IO异常时抛出此异常
|
* @throws WatchException 监听异常,IO异常时抛出此异常
|
||||||
@ -195,7 +193,9 @@ public class WatchMonitor extends Thread implements Closeable, Serializable {
|
|||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
*/
|
*/
|
||||||
private void doTakeAndWatch(final Watcher watcher) {
|
private void doTakeAndWatch(final Watcher watcher) {
|
||||||
this.watchService.watch(watcher, watchEvent -> null == file || file.endsWith(watchEvent.context().toString()));
|
this.watchService.watch(watcher,
|
||||||
|
// 对于文件监听,忽略目录下其他文件和目录的事件
|
||||||
|
watchEvent -> null == file || file.endsWith(watchEvent.context().toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,8 +25,11 @@ import java.util.function.BiConsumer;
|
|||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link WatchEvent} 包装类,提供可选的监听事件和监听选项<br>
|
* {@link WatchEvent} 包装类,提供可选的监听事件和监听选项,实现方法包括:
|
||||||
* 通过多次调用{@link #registerPath(Path, int)} 可以递归注册多个路径
|
* <ul>
|
||||||
|
* <li>注册:{@link #registerPath(Path, int)}注册需要监听的路径。</li>
|
||||||
|
* <li>监听:{@link #watch(Watcher, Predicate)} 启动监听并指定事件触发后的行为。</li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
@ -34,12 +37,22 @@ import java.util.function.Predicate;
|
|||||||
public class WatchServiceWrapper implements WatchService, Wrapper<WatchService>, Serializable {
|
public class WatchServiceWrapper implements WatchService, Wrapper<WatchService>, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建WatchServiceWrapper
|
||||||
|
*
|
||||||
|
* @param events 监听事件列表,如新建、修改、删除等
|
||||||
|
* @return WatchServiceWrapper
|
||||||
|
*/
|
||||||
|
public static WatchServiceWrapper of(final WatchEvent.Kind<?>... events) {
|
||||||
|
return new WatchServiceWrapper(events);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监听服务
|
* 监听服务
|
||||||
*/
|
*/
|
||||||
private final WatchService watchService;
|
private final WatchService watchService;
|
||||||
/**
|
/**
|
||||||
* 监听事件列表
|
* 监听事件列表,如新建、修改、删除等
|
||||||
*/
|
*/
|
||||||
private WatchEvent.Kind<?>[] events;
|
private WatchEvent.Kind<?>[] events;
|
||||||
/**
|
/**
|
||||||
@ -53,8 +66,10 @@ public class WatchServiceWrapper implements WatchService, Wrapper<WatchService>,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
*
|
||||||
|
* @param events 监听事件列表
|
||||||
*/
|
*/
|
||||||
public WatchServiceWrapper() {
|
public WatchServiceWrapper(final WatchEvent.Kind<?>... events) {
|
||||||
//初始化监听
|
//初始化监听
|
||||||
try {
|
try {
|
||||||
watchService = FileSystems.getDefault().newWatchService();
|
watchService = FileSystems.getDefault().newWatchService();
|
||||||
@ -62,7 +77,7 @@ public class WatchServiceWrapper implements WatchService, Wrapper<WatchService>,
|
|||||||
throw new WatchException(e);
|
throw new WatchException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
isClosed = false;
|
this.events = events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -148,6 +163,8 @@ public class WatchServiceWrapper implements WatchService, Wrapper<WatchService>,
|
|||||||
*
|
*
|
||||||
* @param watchable 可注册对象,如Path
|
* @param watchable 可注册对象,如Path
|
||||||
* @return {@link WatchKey},如果为{@code null},表示注册失败
|
* @return {@link WatchKey},如果为{@code null},表示注册失败
|
||||||
|
* @see Watchable#register(WatchService, WatchEvent.Kind[])
|
||||||
|
* @see Watchable#register(WatchService, WatchEvent.Kind[], WatchEvent.Modifier...)
|
||||||
*/
|
*/
|
||||||
public WatchKey register(final Watchable watchable) {
|
public WatchKey register(final Watchable watchable) {
|
||||||
final WatchEvent.Kind<?>[] kinds = ArrayUtil.defaultIfEmpty(this.events, WatchKind.ALL);
|
final WatchEvent.Kind<?>[] kinds = ArrayUtil.defaultIfEmpty(this.events, WatchKind.ALL);
|
||||||
@ -174,17 +191,18 @@ public class WatchServiceWrapper implements WatchService, Wrapper<WatchService>,
|
|||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param maxDepth 递归下层目录的最大深度
|
* @param maxDepth 递归下层目录的最大深度
|
||||||
|
* @return this
|
||||||
*/
|
*/
|
||||||
public void registerPath(final Path path, final int maxDepth) {
|
public WatchServiceWrapper registerPath(final Path path, final int maxDepth) {
|
||||||
// 注册当前目录或文件
|
// 注册当前目录或文件
|
||||||
final WatchKey watchKey = register(path);
|
if (null == register(path)) {
|
||||||
if (null == watchKey) {
|
|
||||||
// 注册失败,跳过(可能目录或文件无权限)
|
// 注册失败,跳过(可能目录或文件无权限)
|
||||||
return;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 递归注册下一层层级的目录和文件
|
// 递归注册下一层层级的目录和文件
|
||||||
PathUtil.walkFiles(path, maxDepth, new SimpleFileVisitor<Path>() {
|
PathUtil.walkFiles(path, maxDepth, new SimpleFileVisitor<Path>() {
|
||||||
|
@SuppressWarnings("resource")
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
|
public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
|
||||||
//继续添加目录
|
//继续添加目录
|
||||||
@ -192,10 +210,14 @@ public class WatchServiceWrapper implements WatchService, Wrapper<WatchService>,
|
|||||||
return super.postVisitDirectory(dir, exc);
|
return super.postVisitDirectory(dir, exc);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行事件获取并处理
|
* 执行事件获取并处理<br>
|
||||||
|
* {@link WatchEvent#context()}是实际操作的文件或目录的相对监听路径的Path,非绝对路径<br>
|
||||||
|
* {@link WatchKey#watchable()}是监听的Path<br>
|
||||||
|
* 此方法调用后阻塞线程,直到触发监听事件,执行后退出,无循环执行操作
|
||||||
*
|
*
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @param watchFilter 监听过滤接口,通过实现此接口过滤掉不需要监听的情况,{@link Predicate#test(Object)}为{@code true}保留,null表示不过滤
|
* @param watchFilter 监听过滤接口,通过实现此接口过滤掉不需要监听的情况,{@link Predicate#test(Object)}为{@code true}保留,null表示不过滤
|
||||||
@ -217,7 +239,22 @@ public class WatchServiceWrapper implements WatchService, Wrapper<WatchService>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行事件获取并处理
|
* 执行事件获取并处理<br>
|
||||||
|
* {@link WatchEvent#context()}是实际操作的文件或目录的相对监听路径的Path,非绝对路径<br>
|
||||||
|
* {@link WatchKey#watchable()}是监听的Path<br>
|
||||||
|
* 此方法调用后阻塞线程,直到触发监听事件,执行后退出,无循环执行操作
|
||||||
|
*
|
||||||
|
* @param action 监听回调函数,实现此函数接口用于处理WatchEvent事件
|
||||||
|
*/
|
||||||
|
public void watch(final BiConsumer<WatchEvent<?>, WatchKey> action) {
|
||||||
|
watch(action, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行事件获取并处理<br>
|
||||||
|
* {@link WatchEvent#context()}是实际操作的文件或目录的相对监听路径的Path,非绝对路径<br>
|
||||||
|
* {@link WatchKey#watchable()}是监听的Path<br>
|
||||||
|
* 此方法调用后阻塞线程,直到触发监听事件,执行后退出,无循环执行操作
|
||||||
*
|
*
|
||||||
* @param action 监听回调函数,实现此函数接口用于处理WatchEvent事件
|
* @param action 监听回调函数,实现此函数接口用于处理WatchEvent事件
|
||||||
* @param watchFilter 监听过滤接口,通过实现此接口过滤掉不需要监听的情况,{@link Predicate#test(Object)}为{@code true}保留,null表示不过滤
|
* @param watchFilter 监听过滤接口,通过实现此接口过滤掉不需要监听的情况,{@link Predicate#test(Object)}为{@code true}保留,null表示不过滤
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
package org.dromara.hutool.core.io.watch;
|
package org.dromara.hutool.core.io.watch;
|
||||||
|
|
||||||
import org.dromara.hutool.core.io.IORuntimeException;
|
import org.dromara.hutool.core.io.IORuntimeException;
|
||||||
|
import org.dromara.hutool.core.io.file.PathUtil;
|
||||||
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
import org.dromara.hutool.core.net.url.UrlUtil;
|
import org.dromara.hutool.core.net.url.UrlUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -36,10 +38,11 @@ import java.nio.file.Watchable;
|
|||||||
public class WatchUtil {
|
public class WatchUtil {
|
||||||
|
|
||||||
// region ----- of
|
// region ----- of
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建并初始化监听
|
* 创建并初始化监听
|
||||||
*
|
*
|
||||||
* @param url URL
|
* @param url URL
|
||||||
* @param events 监听的事件列表
|
* @param events 监听的事件列表
|
||||||
* @return 监听对象
|
* @return 监听对象
|
||||||
*/
|
*/
|
||||||
@ -50,8 +53,8 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听
|
* 创建并初始化监听
|
||||||
*
|
*
|
||||||
* @param url URL
|
* @param url URL
|
||||||
* @param events 监听的事件列表
|
* @param events 监听的事件列表
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @return 监听对象
|
* @return 监听对象
|
||||||
*/
|
*/
|
||||||
@ -62,7 +65,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听
|
* 创建并初始化监听
|
||||||
*
|
*
|
||||||
* @param uri URI
|
* @param uri URI
|
||||||
* @param events 监听的事件列表
|
* @param events 监听的事件列表
|
||||||
* @return 监听对象
|
* @return 监听对象
|
||||||
*/
|
*/
|
||||||
@ -73,8 +76,8 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听
|
* 创建并初始化监听
|
||||||
*
|
*
|
||||||
* @param uri URI
|
* @param uri URI
|
||||||
* @param events 监听的事件列表
|
* @param events 监听的事件列表
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @return 监听对象
|
* @return 监听对象
|
||||||
*/
|
*/
|
||||||
@ -85,7 +88,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听
|
* 创建并初始化监听
|
||||||
*
|
*
|
||||||
* @param file 文件
|
* @param file 文件
|
||||||
* @param events 监听的事件列表
|
* @param events 监听的事件列表
|
||||||
* @return 监听对象
|
* @return 监听对象
|
||||||
*/
|
*/
|
||||||
@ -96,8 +99,8 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听
|
* 创建并初始化监听
|
||||||
*
|
*
|
||||||
* @param file 文件
|
* @param file 文件
|
||||||
* @param events 监听的事件列表
|
* @param events 监听的事件列表
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @return 监听对象
|
* @return 监听对象
|
||||||
*/
|
*/
|
||||||
@ -108,7 +111,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听
|
* 创建并初始化监听
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param events 监听的事件列表
|
* @param events 监听的事件列表
|
||||||
* @return 监听对象
|
* @return 监听对象
|
||||||
*/
|
*/
|
||||||
@ -119,8 +122,8 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听
|
* 创建并初始化监听
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param events 监听的事件列表
|
* @param events 监听的事件列表
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @return 监听对象
|
* @return 监听对象
|
||||||
*/
|
*/
|
||||||
@ -131,7 +134,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听
|
* 创建并初始化监听
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param events 监听事件列表
|
* @param events 监听事件列表
|
||||||
* @return 监听对象
|
* @return 监听对象
|
||||||
*/
|
*/
|
||||||
@ -142,8 +145,8 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听
|
* 创建并初始化监听
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param events 监听事件列表
|
* @param events 监听事件列表
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @return 监听对象
|
* @return 监听对象
|
||||||
*/
|
*/
|
||||||
@ -153,10 +156,11 @@ public class WatchUtil {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region ----- ofAll
|
// region ----- ofAll
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听所有事件
|
* 创建并初始化监听,监听所有事件
|
||||||
*
|
*
|
||||||
* @param url URL
|
* @param url URL
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
*/
|
*/
|
||||||
@ -167,9 +171,9 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听所有事件
|
* 创建并初始化监听,监听所有事件
|
||||||
*
|
*
|
||||||
* @param url URL
|
* @param url URL
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
*/
|
*/
|
||||||
public static WatchMonitor ofAll(final URL url, final int maxDepth, final Watcher watcher) {
|
public static WatchMonitor ofAll(final URL url, final int maxDepth, final Watcher watcher) {
|
||||||
@ -179,7 +183,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听所有事件
|
* 创建并初始化监听,监听所有事件
|
||||||
*
|
*
|
||||||
* @param uri URI
|
* @param uri URI
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
*/
|
*/
|
||||||
@ -190,9 +194,9 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听所有事件
|
* 创建并初始化监听,监听所有事件
|
||||||
*
|
*
|
||||||
* @param uri URI
|
* @param uri URI
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
*/
|
*/
|
||||||
public static WatchMonitor ofAll(final URI uri, final int maxDepth, final Watcher watcher) {
|
public static WatchMonitor ofAll(final URI uri, final int maxDepth, final Watcher watcher) {
|
||||||
@ -202,7 +206,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听所有事件
|
* 创建并初始化监听,监听所有事件
|
||||||
*
|
*
|
||||||
* @param file 被监听文件
|
* @param file 被监听文件
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
*/
|
*/
|
||||||
@ -213,9 +217,9 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听所有事件
|
* 创建并初始化监听,监听所有事件
|
||||||
*
|
*
|
||||||
* @param file 被监听文件
|
* @param file 被监听文件
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
*/
|
*/
|
||||||
public static WatchMonitor ofAll(final File file, final int maxDepth, final Watcher watcher) {
|
public static WatchMonitor ofAll(final File file, final int maxDepth, final Watcher watcher) {
|
||||||
@ -225,7 +229,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听所有事件
|
* 创建并初始化监听,监听所有事件
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
*/
|
*/
|
||||||
@ -236,9 +240,9 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听所有事件
|
* 创建并初始化监听,监听所有事件
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
*/
|
*/
|
||||||
public static WatchMonitor ofAll(final String path, final int maxDepth, final Watcher watcher) {
|
public static WatchMonitor ofAll(final String path, final int maxDepth, final Watcher watcher) {
|
||||||
@ -248,7 +252,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听所有事件
|
* 创建并初始化监听,监听所有事件
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
*/
|
*/
|
||||||
@ -259,9 +263,9 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听所有事件
|
* 创建并初始化监听,监听所有事件
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("resource")
|
@SuppressWarnings("resource")
|
||||||
@ -271,10 +275,11 @@ public class WatchUtil {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region ----- ofModify
|
// region ----- ofModify
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听修改事件
|
* 创建并初始化监听,监听修改事件
|
||||||
*
|
*
|
||||||
* @param url URL
|
* @param url URL
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
@ -286,9 +291,9 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听修改事件
|
* 创建并初始化监听,监听修改事件
|
||||||
*
|
*
|
||||||
* @param url URL
|
* @param url URL
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
*/
|
*/
|
||||||
@ -299,7 +304,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听修改事件
|
* 创建并初始化监听,监听修改事件
|
||||||
*
|
*
|
||||||
* @param uri URI
|
* @param uri URI
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
@ -311,9 +316,9 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听修改事件
|
* 创建并初始化监听,监听修改事件
|
||||||
*
|
*
|
||||||
* @param uri URI
|
* @param uri URI
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
*/
|
*/
|
||||||
@ -324,7 +329,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听修改事件
|
* 创建并初始化监听,监听修改事件
|
||||||
*
|
*
|
||||||
* @param file 被监听文件
|
* @param file 被监听文件
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
@ -336,9 +341,9 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听修改事件
|
* 创建并初始化监听,监听修改事件
|
||||||
*
|
*
|
||||||
* @param file 被监听文件
|
* @param file 被监听文件
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
*/
|
*/
|
||||||
@ -349,7 +354,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听修改事件
|
* 创建并初始化监听,监听修改事件
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
@ -361,9 +366,9 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听修改事件
|
* 创建并初始化监听,监听修改事件
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
*/
|
*/
|
||||||
@ -374,7 +379,7 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听修改事件
|
* 创建并初始化监听,监听修改事件
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
@ -386,9 +391,9 @@ public class WatchUtil {
|
|||||||
/**
|
/**
|
||||||
* 创建并初始化监听,监听修改事件
|
* 创建并初始化监听,监听修改事件
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
* @param maxDepth 当监听目录时,监听目录的最大深度,当设置值为1(或小于1)时,表示不递归监听子目录
|
||||||
* @param watcher {@link Watcher}
|
* @param watcher {@link Watcher}
|
||||||
* @return {@link WatchMonitor}
|
* @return {@link WatchMonitor}
|
||||||
* @since 4.5.2
|
* @since 4.5.2
|
||||||
*/
|
*/
|
||||||
@ -403,16 +408,30 @@ public class WatchUtil {
|
|||||||
* 注册Watchable对象到WatchService服务
|
* 注册Watchable对象到WatchService服务
|
||||||
*
|
*
|
||||||
* @param watchable 可注册对象
|
* @param watchable 可注册对象
|
||||||
* @param watcher WatchService对象
|
* @param watcher WatchService对象
|
||||||
* @param events 监听事件
|
* @param events 监听事件
|
||||||
* @return {@link WatchKey}
|
* @return {@link WatchKey}
|
||||||
* @since 4.6.9
|
* @since 4.6.9
|
||||||
*/
|
*/
|
||||||
public static WatchKey register(final Watchable watchable, final WatchService watcher, final WatchEvent.Kind<?>... events){
|
public static WatchKey register(final Watchable watchable, final WatchService watcher, final WatchEvent.Kind<?>... events) {
|
||||||
try {
|
try {
|
||||||
return watchable.register(watcher, events);
|
return watchable.register(watcher, events);
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
throw new IORuntimeException(e);
|
throw new IORuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取触发事件中相对监听Path的完整路径
|
||||||
|
*
|
||||||
|
* @param event 事件
|
||||||
|
* @param key {@link WatchKey}
|
||||||
|
* @return 完整路径
|
||||||
|
*/
|
||||||
|
public static Path resolvePath(final WatchEvent<?> event, final WatchKey key) {
|
||||||
|
Assert.notNull(event, "WatchEvent must be not null!");
|
||||||
|
Assert.notNull(event, "WatchKey must be not null!");
|
||||||
|
|
||||||
|
return PathUtil.of((Path) key.watchable(), (Path) event.context());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ public interface Watcher {
|
|||||||
/**
|
/**
|
||||||
* 文件创建时执行的方法
|
* 文件创建时执行的方法
|
||||||
*
|
*
|
||||||
* @param event 事件
|
* @param event 事件,可通过{@link WatchEvent#context()}获取创建的文件或目录名称
|
||||||
* @param key 事件发生的{@link WatchKey},可以通过{@link WatchKey#watchable()}获取监听的Path路径
|
* @param key 事件发生的{@link WatchKey},可以通过{@link WatchKey#watchable()}获取监听的Path路径
|
||||||
*/
|
*/
|
||||||
void onCreate(WatchEvent<?> event, WatchKey key);
|
void onCreate(WatchEvent<?> event, WatchKey key);
|
||||||
@ -33,7 +33,7 @@ public interface Watcher {
|
|||||||
* 文件修改时执行的方法<br>
|
* 文件修改时执行的方法<br>
|
||||||
* 文件修改可能触发多次
|
* 文件修改可能触发多次
|
||||||
*
|
*
|
||||||
* @param event 事件
|
* @param event 事件,可通过{@link WatchEvent#context()}获取创建的文件或目录名称
|
||||||
* @param key 事件发生的{@link WatchKey},可以通过{@link WatchKey#watchable()}获取监听的Path路径
|
* @param key 事件发生的{@link WatchKey},可以通过{@link WatchKey#watchable()}获取监听的Path路径
|
||||||
*/
|
*/
|
||||||
void onModify(WatchEvent<?> event, WatchKey key);
|
void onModify(WatchEvent<?> event, WatchKey key);
|
||||||
@ -41,7 +41,7 @@ public interface Watcher {
|
|||||||
/**
|
/**
|
||||||
* 文件删除时执行的方法
|
* 文件删除时执行的方法
|
||||||
*
|
*
|
||||||
* @param event 事件
|
* @param event 事件,可通过{@link WatchEvent#context()}获取创建的文件或目录名称
|
||||||
* @param key 事件发生的{@link WatchKey},可以通过{@link WatchKey#watchable()}获取监听的Path路径
|
* @param key 事件发生的{@link WatchKey},可以通过{@link WatchKey#watchable()}获取监听的Path路径
|
||||||
*/
|
*/
|
||||||
void onDelete(WatchEvent<?> event, WatchKey key);
|
void onDelete(WatchEvent<?> event, WatchKey key);
|
||||||
@ -49,7 +49,7 @@ public interface Watcher {
|
|||||||
/**
|
/**
|
||||||
* 事件丢失或出错时执行的方法
|
* 事件丢失或出错时执行的方法
|
||||||
*
|
*
|
||||||
* @param event 事件
|
* @param event 事件,可通过{@link WatchEvent#context()}获取创建的文件或目录名称
|
||||||
* @param key 事件发生的{@link WatchKey},可以通过{@link WatchKey#watchable()}获取监听的Path路径
|
* @param key 事件发生的{@link WatchKey},可以通过{@link WatchKey#watchable()}获取监听的Path路径
|
||||||
*/
|
*/
|
||||||
void onOverflow(WatchEvent<?> event, WatchKey key);
|
void onOverflow(WatchEvent<?> event, WatchKey key);
|
||||||
|
@ -32,22 +32,30 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class DelayWatcher implements Watcher {
|
public class DelayWatcher implements Watcher {
|
||||||
|
|
||||||
/** Path集合。此集合用于去重在指定delay内多次触发的文件Path */
|
/**
|
||||||
|
* Path集合。此集合用于去重在指定delay内多次触发的文件Path
|
||||||
|
*/
|
||||||
private final Set<Path> eventSet = new ConcurrentHashSet<>();
|
private final Set<Path> eventSet = new ConcurrentHashSet<>();
|
||||||
/** 实际处理 */
|
/**
|
||||||
|
* 实际处理
|
||||||
|
*/
|
||||||
private final Watcher watcher;
|
private final Watcher watcher;
|
||||||
/** 延迟,单位毫秒 */
|
/**
|
||||||
|
* 延迟,单位毫秒
|
||||||
|
*/
|
||||||
private final long delay;
|
private final long delay;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------- Constructor start
|
//---------------------------------------------------------------------------------------------------------- Constructor start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
*
|
||||||
* @param watcher 实际处理触发事件的监视器{@link Watcher},不可以是{@code DelayWatcher}
|
* @param watcher 实际处理触发事件的监视器{@link Watcher},不可以是{@code DelayWatcher}
|
||||||
* @param delay 延迟时间,单位毫秒
|
* @param delay 延迟时间,单位毫秒
|
||||||
*/
|
*/
|
||||||
public DelayWatcher(final Watcher watcher, final long delay) {
|
public DelayWatcher(final Watcher watcher, final long delay) {
|
||||||
Assert.notNull(watcher);
|
Assert.notNull(watcher);
|
||||||
if(watcher instanceof DelayWatcher) {
|
if (watcher instanceof DelayWatcher) {
|
||||||
throw new IllegalArgumentException("Watcher must not be a DelayWatcher");
|
throw new IllegalArgumentException("Watcher must not be a DelayWatcher");
|
||||||
}
|
}
|
||||||
this.watcher = watcher;
|
this.watcher = watcher;
|
||||||
@ -57,9 +65,9 @@ public class DelayWatcher implements Watcher {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onModify(final WatchEvent<?> event, final WatchKey key) {
|
public void onModify(final WatchEvent<?> event, final WatchKey key) {
|
||||||
if(this.delay < 1) {
|
if (this.delay < 1) {
|
||||||
this.watcher.onModify(event, key);
|
this.watcher.onModify(event, key);
|
||||||
}else {
|
} else {
|
||||||
onDelayModify(event, key);
|
onDelayModify(event, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,14 +88,16 @@ public class DelayWatcher implements Watcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------- Private method start
|
//---------------------------------------------------------------------------------------------------------- Private method start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 触发延迟修改
|
* 触发延迟修改
|
||||||
|
*
|
||||||
* @param event 事件
|
* @param event 事件
|
||||||
* @param key {@link WatchKey}
|
* @param key {@link WatchKey}
|
||||||
*/
|
*/
|
||||||
private void onDelayModify(final WatchEvent<?> event, final WatchKey key) {
|
private void onDelayModify(final WatchEvent<?> event, final WatchKey key) {
|
||||||
final Path eventPath = Paths.get(key.watchable().toString(), event.context().toString());
|
final Path eventPath = Paths.get(key.watchable().toString(), event.context().toString());
|
||||||
if(eventSet.contains(eventPath)) {
|
if (eventSet.contains(eventPath)) {
|
||||||
//此事件已经被触发过,后续事件忽略,等待统一处理。
|
//此事件已经被触发过,后续事件忽略,等待统一处理。
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -101,7 +111,7 @@ public class DelayWatcher implements Watcher {
|
|||||||
* 开启处理线程
|
* 开启处理线程
|
||||||
*
|
*
|
||||||
* @param event 事件
|
* @param event 事件
|
||||||
* @param currentPath 事件发生的当前Path路径
|
* @param key 事件发生的当前WatchKey
|
||||||
*/
|
*/
|
||||||
private void startHandleModifyThread(final WatchEvent<?> event, final WatchKey key) {
|
private void startHandleModifyThread(final WatchEvent<?> event, final WatchKey key) {
|
||||||
ThreadUtil.execute(() -> {
|
ThreadUtil.execute(() -> {
|
||||||
|
@ -1,44 +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.core.io.watch.watchers;
|
|
||||||
|
|
||||||
import org.dromara.hutool.core.io.watch.Watcher;
|
|
||||||
|
|
||||||
import java.nio.file.WatchEvent;
|
|
||||||
import java.nio.file.WatchKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳过所有事件处理Watcher<br>
|
|
||||||
* 用户继承此类后实现需要监听的方法
|
|
||||||
*
|
|
||||||
* @author Looly
|
|
||||||
* @since 3.1.0
|
|
||||||
*/
|
|
||||||
public class IgnoreWatcher implements Watcher {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(final WatchEvent<?> event, final WatchKey key) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onModify(final WatchEvent<?> event, final WatchKey key) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDelete(final WatchEvent<?> event, final WatchKey key) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOverflow(final WatchEvent<?> event, final WatchKey key) {
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,11 +12,34 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.io.watch.watchers;
|
package org.dromara.hutool.core.io.watch.watchers;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.io.watch.Watcher;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.nio.file.WatchEvent;
|
||||||
|
import java.nio.file.WatchKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 空白WatchListener<br>
|
* 空白WatchListener<br>
|
||||||
* 用户继承此类后实现需要监听的方法
|
* 用户继承此类后实现需要监听的方法
|
||||||
* @author Looly
|
|
||||||
*
|
*
|
||||||
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class SimpleWatcher extends IgnoreWatcher {
|
public class SimpleWatcher implements Watcher, Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(final WatchEvent<?> event, final WatchKey key) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onModify(final WatchEvent<?> event, final WatchKey key) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDelete(final WatchEvent<?> event, final WatchKey key) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOverflow(final WatchEvent<?> event, final WatchKey key) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ public interface RegexPool {
|
|||||||
* 车架号(车辆识别代号由世界制造厂识别代号(WMI、车辆说明部分(VDS)车辆指示部分(VIS)三部分组成,共 17 位字码。)<br>
|
* 车架号(车辆识别代号由世界制造厂识别代号(WMI、车辆说明部分(VDS)车辆指示部分(VIS)三部分组成,共 17 位字码。)<br>
|
||||||
* 别名:车辆识别代号、车辆识别码、车架号、十七位码<br>
|
* 别名:车辆识别代号、车辆识别码、车架号、十七位码<br>
|
||||||
* 标准号:GB 16735-2019<br>
|
* 标准号:GB 16735-2019<br>
|
||||||
* 标准官方地址:https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=E2EBF667F8C032B1EDFD6DF9C1114E02
|
* 标准官方地址:https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=E2EBF667F8C032B1EDFD6DF9C1114E02<br>
|
||||||
* 对年产量大于或等于1 000 辆的完整车辆和/或非完整车辆制造厂:
|
* 对年产量大于或等于1 000 辆的完整车辆和/或非完整车辆制造厂:
|
||||||
* <pre>
|
* <pre>
|
||||||
* 第一部分为世界制造厂识别代号(WMI),3位
|
* 第一部分为世界制造厂识别代号(WMI),3位
|
||||||
|
@ -0,0 +1,105 @@
|
|||||||
|
package org.dromara.hutool.core.text;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
|
import org.dromara.hutool.core.collection.iter.ArrayIter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* char[]包装,提供zero-copy的数组操作
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
*/
|
||||||
|
public class CharArray implements CharSequence, Iterable<Character> {
|
||||||
|
|
||||||
|
private final char[] value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param value String值
|
||||||
|
*/
|
||||||
|
public CharArray(final String value) {
|
||||||
|
this(value.toCharArray(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造,注意此方法共享数组
|
||||||
|
*
|
||||||
|
* @param value char数组
|
||||||
|
* @param copy 可选是否拷贝数组,如果为{@code false}则复用数组
|
||||||
|
*/
|
||||||
|
public CharArray(final char[] value, final boolean copy) {
|
||||||
|
this.value = copy ? value.clone() : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int length() {
|
||||||
|
return value.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char charAt(int index) {
|
||||||
|
if (index < 0) {
|
||||||
|
index += value.length;
|
||||||
|
}
|
||||||
|
return value[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置字符
|
||||||
|
*
|
||||||
|
* @param index 位置,支持复数,-1表示最后一个位置
|
||||||
|
* @param c 字符
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public CharArray set(int index, final char c) {
|
||||||
|
if (index < 0) {
|
||||||
|
index += value.length;
|
||||||
|
}
|
||||||
|
value[index] = c;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取原始数组,不做拷贝
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public char[] array() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence subSequence(final int start, final int end) {
|
||||||
|
return new CharArray(ArrayUtil.sub(value, start, end), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final CharArray charArray = (CharArray) o;
|
||||||
|
return Arrays.equals(value, charArray.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Arrays.hashCode(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Character> iterator() {
|
||||||
|
return new ArrayIter<>(this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(this.value);
|
||||||
|
}
|
||||||
|
}
|
@ -1,70 +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.core.io;
|
|
||||||
|
|
||||||
import org.dromara.hutool.core.io.watch.WatchMonitor;
|
|
||||||
import org.dromara.hutool.core.io.watch.WatchUtil;
|
|
||||||
import org.dromara.hutool.core.io.watch.Watcher;
|
|
||||||
import org.dromara.hutool.core.io.watch.watchers.DelayWatcher;
|
|
||||||
import org.dromara.hutool.core.io.watch.watchers.SimpleWatcher;
|
|
||||||
import org.dromara.hutool.core.lang.Console;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.WatchEvent;
|
|
||||||
import java.nio.file.WatchKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件监听单元测试
|
|
||||||
*
|
|
||||||
* @author Looly
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class WatchMonitorTest {
|
|
||||||
|
|
||||||
public static void main(final String[] args) {
|
|
||||||
final Watcher watcher = new SimpleWatcher(){
|
|
||||||
@Override
|
|
||||||
public void onCreate(final WatchEvent<?> event, final WatchKey key) {
|
|
||||||
final Object obj = event.context();
|
|
||||||
Console.log(((Path)obj).toAbsolutePath());
|
|
||||||
Console.log("创建:{}-> {}", key.watchable(), obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onModify(final WatchEvent<?> event, final WatchKey key) {
|
|
||||||
final Object obj = event.context();
|
|
||||||
Console.log("修改:{}-> {}", key.watchable(), obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDelete(final WatchEvent<?> event, final WatchKey key) {
|
|
||||||
final Object obj = event.context();
|
|
||||||
Console.log("删除:{}-> {}", key.watchable(), obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOverflow(final WatchEvent<?> event, final WatchKey key) {
|
|
||||||
final Object obj = event.context();
|
|
||||||
Console.log("Overflow:{}-> {}", key.watchable(), obj);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection resource
|
|
||||||
final WatchMonitor monitor = WatchUtil.ofAll("d:/test/aaa.txt", new DelayWatcher(watcher, 500));
|
|
||||||
|
|
||||||
monitor.setMaxDepth(0);
|
|
||||||
monitor.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -13,15 +13,35 @@
|
|||||||
package org.dromara.hutool.core.io.file;
|
package org.dromara.hutool.core.io.file;
|
||||||
|
|
||||||
import org.dromara.hutool.core.array.ArrayUtil;
|
import org.dromara.hutool.core.array.ArrayUtil;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
|
|
||||||
public class PathUtilTest {
|
public class PathUtilTest {
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicateExpressions")
|
||||||
|
@Test
|
||||||
|
void ofTest() {
|
||||||
|
// 绝对路径测试
|
||||||
|
Path path = PathUtil.of(Paths.get("d:/test/hutool"), Paths.get("data1"), Paths.get("data2"));
|
||||||
|
Assertions.assertEquals("d:/test/hutool/data1/data2", path.toString().replace('\\', '/'));
|
||||||
|
|
||||||
|
// 相对路径测试
|
||||||
|
path = PathUtil.of(Paths.get("hutool"), Paths.get("data1"), Paths.get("data2"));
|
||||||
|
Assertions.assertEquals("hutool/data1/data2", path.toString().replace('\\', '/'));
|
||||||
|
|
||||||
|
path = PathUtil.of(Paths.get("hutool"));
|
||||||
|
Assertions.assertEquals("hutool", path.toString().replace('\\', '/'));
|
||||||
|
|
||||||
|
path = PathUtil.of((Path) null);
|
||||||
|
Assertions.assertNull(path);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
@Disabled
|
||||||
public void copyFileTest(){
|
public void copyFileTest(){
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package org.dromara.hutool.core.io.watch;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.io.watch.watchers.SimpleWatcher;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
|
|
||||||
|
import java.nio.file.WatchEvent;
|
||||||
|
import java.nio.file.WatchKey;
|
||||||
|
|
||||||
|
public class TestConsoleWatcher extends SimpleWatcher {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(final WatchEvent<?> event, final WatchKey key) {
|
||||||
|
Console.log("创建:{}-> {}", key.watchable(), event.context());
|
||||||
|
Console.log("Resolved Path:{}", WatchUtil.resolvePath(event, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onModify(final WatchEvent<?> event, final WatchKey key) {
|
||||||
|
Console.log("修改:{}-> {}", key.watchable(), event.context());
|
||||||
|
Console.log("Resolved Path:{}", WatchUtil.resolvePath(event, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDelete(final WatchEvent<?> event, final WatchKey key) {
|
||||||
|
Console.log("删除:{}-> {}", key.watchable(), event.context());
|
||||||
|
Console.log("Resolved Path:{}", WatchUtil.resolvePath(event, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOverflow(final WatchEvent<?> event, final WatchKey key) {
|
||||||
|
Console.log("Overflow:{}-> {}", key.watchable(), event.context());
|
||||||
|
Console.log("Resolved Path:{}", WatchUtil.resolvePath(event, key));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.core.io.watch;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.io.file.PathUtil;
|
||||||
|
import org.dromara.hutool.core.io.watch.watchers.DelayWatcher;
|
||||||
|
import org.dromara.hutool.core.io.watch.watchers.SimpleWatcher;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.WatchEvent;
|
||||||
|
import java.nio.file.WatchKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件监听单元测试
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
*/
|
||||||
|
public class WatchMonitorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
void watchTest() {
|
||||||
|
final Path path = PathUtil.of("d:/test/");
|
||||||
|
Console.log("监听:{}", path);
|
||||||
|
|
||||||
|
//noinspection resource
|
||||||
|
final WatchMonitor monitor = WatchUtil.ofAll(path, new DelayWatcher(new TestConsoleWatcher(), 500));
|
||||||
|
monitor.setMaxDepth(0);
|
||||||
|
monitor.start();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package org.dromara.hutool.core.io.watch;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.io.file.PathUtil;
|
||||||
|
import org.dromara.hutool.core.io.watch.watchers.SimpleWatcher;
|
||||||
|
import org.dromara.hutool.core.lang.Console;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.file.WatchEvent;
|
||||||
|
import java.nio.file.WatchKey;
|
||||||
|
|
||||||
|
public class WatchServiceWrapperTest {
|
||||||
|
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
void watchTest() {
|
||||||
|
WatchServiceWrapper.of(WatchKind.ALL)
|
||||||
|
.registerPath(PathUtil.of("d:/test"), 0)
|
||||||
|
.watch(new TestConsoleWatcher(), null);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user