浏览代码

fix watch

Looly 6 年之前
父节点
当前提交
a5e9f119b6

+ 10 - 133
hutool-core/src/main/java/cn/hutool/core/io/watch/WatchMonitor.java

@@ -2,23 +2,22 @@ package cn.hutool.core.io.watch;
 
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.io.IORuntimeException;
-import cn.hutool.core.io.IoUtil;
 import cn.hutool.core.io.watch.watchers.WatcherChain;
-import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.URLUtil;
 
-import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
-import java.io.Serializable;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
-import java.nio.file.*;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchService;
 
 /**
  * 路径监听器
@@ -30,7 +29,7 @@ import java.util.Map;
  *
  * @author Looly
  */
-public class WatchMonitor extends Thread implements Closeable, Serializable {
+public class WatchMonitor extends WatchServer {
 	private static final long serialVersionUID = 1L;
 
 	/**
@@ -73,32 +72,9 @@ public class WatchMonitor extends Thread implements Closeable, Serializable {
 	private Path filePath;
 
 	/**
-	 * 监听服务
-	 */
-	private WatchService watchService;
-	/**
 	 * 监听器
 	 */
 	private Watcher watcher;
-	/**
-	 * 监听事件列表
-	 */
-	private WatchEvent.Kind<?>[] events;
-	/**
-	 * 监听选项,例如监听频率等
-	 */
-	private WatchEvent.Modifier[] modifiers;
-
-	/**
-	 * 监听是否已经关闭
-	 */
-	private boolean isClosed;
-
-	/**
-	 * WatchKey 和 Path的对应表
-	 */
-	private Map<WatchKey, Path> watchKeyPathMap = new HashMap<>();
-
 	//------------------------------------------------------ Static method start
 
 	/**
@@ -369,14 +345,7 @@ public class WatchMonitor extends Thread implements Closeable, Serializable {
 			this.path = this.filePath.getParent();
 		}
 
-		//初始化监听
-		try {
-			watchService = FileSystems.getDefault().newWatchService();
-		} catch (IOException e) {
-			throw new WatchException(e);
-		}
-
-		isClosed = false;
+		super.init();
 	}
 
 	/**
@@ -441,31 +410,6 @@ public class WatchMonitor extends Thread implements Closeable, Serializable {
 		return this;
 	}
 
-	/**
-	 * 设置监听选项,例如监听频率等,可设置项包括:
-	 *
-	 * <pre>
-	 * 1、com.sun.nio.file.StandardWatchEventKinds
-	 * 2、com.sun.nio.file.SensitivityWatchEventModifier
-	 * </pre>
-	 *
-	 * @param modifiers 监听选项,例如监听频率等
-	 * @return this
-	 */
-	public WatchMonitor setModifiers(WatchEvent.Modifier[] modifiers) {
-		this.modifiers = modifiers;
-		return this;
-	}
-
-	/**
-	 * 关闭监听
-	 */
-	@Override
-	public void close() {
-		isClosed = true;
-		IoUtil.close(watchService);
-	}
-
 	//------------------------------------------------------ private method start
 
 	/**
@@ -474,36 +418,7 @@ public class WatchMonitor extends Thread implements Closeable, Serializable {
 	 * @param watcher {@link Watcher}
 	 */
 	private void doTakeAndWatch(Watcher watcher) {
-		WatchKey wk;
-		try {
-			wk = watchService.take();
-		} catch (InterruptedException | ClosedWatchServiceException e) {
-			// 用户中断
-			return;
-		}
-
-		final Path currentPath = watchKeyPathMap.get(wk);
-		WatchEvent.Kind<?> kind;
-		for (WatchEvent<?> event : wk.pollEvents()) {
-			kind = event.kind();
-
-			// 如果监听文件,检查当前事件是否与所监听文件关联
-			if (null != this.filePath && false == this.filePath.endsWith(event.context().toString())) {
-//					log.debug("[{}] is not fit for [{}], pass it.", event.context(), this.filePath.getFileName());
-				continue;
-			}
-
-			if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
-				watcher.onCreate(event, currentPath);
-			} else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) {
-				watcher.onModify(event, currentPath);
-			} else if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
-				watcher.onDelete(event, currentPath);
-			} else if (kind == StandardWatchEventKinds.OVERFLOW) {
-				watcher.onOverflow(event, currentPath);
-			}
-		}
-		wk.reset();
+		super.watch(watcher, watchEvent -> null == filePath || filePath.endsWith(watchEvent.context().toString()));
 	}
 
 	/**
@@ -512,43 +427,5 @@ public class WatchMonitor extends Thread implements Closeable, Serializable {
 	private void registerPath() {
 		registerPath(this.path, (null != this.filePath) ? 0 : this.maxDepth);
 	}
-
-	/**
-	 * 将指定路径加入到监听中
-	 *
-	 * @param path     路径
-	 * @param maxDepth 递归下层目录的最大深度
-	 */
-	private void registerPath(Path path, int maxDepth) {
-		final WatchEvent.Kind<?>[] kinds = ArrayUtil.defaultIfEmpty(this.events, EVENTS_ALL);
-
-		try {
-			final WatchKey key;
-			if (ArrayUtil.isEmpty(this.modifiers)) {
-				key = path.register(this.watchService, kinds);
-			} else {
-				key = path.register(this.watchService, kinds, this.modifiers);
-			}
-			watchKeyPathMap.put(key, path);
-
-			// 递归注册下一层层级的目录
-			if (maxDepth > 1) {
-				//遍历所有子目录并加入监听
-				Files.walkFileTree(path, EnumSet.noneOf(FileVisitOption.class), maxDepth, new SimpleFileVisitor<Path>() {
-					@Override
-					public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
-						registerPath(dir, 0);//继续添加目录
-						return super.postVisitDirectory(dir, exc);
-					}
-				});
-			}
-		} catch (IOException e) {
-			if (e instanceof AccessDeniedException) {
-				//对于禁止访问的目录,跳过监听
-				return;
-			}
-			throw new WatchException(e);
-		}
-	}
 	//------------------------------------------------------ private method end
 }

+ 2 - 2
hutool-core/src/main/java/cn/hutool/core/io/watch/WatchServer.java

@@ -39,7 +39,7 @@ public class WatchServer extends Thread implements Closeable, Serializable {
 	/**
 	 * 监听事件列表
 	 */
-	private WatchEvent.Kind<?>[] events;
+	protected WatchEvent.Kind<?>[] events;
 	/**
 	 * 监听选项,例如监听频率等
 	 */
@@ -47,7 +47,7 @@ public class WatchServer extends Thread implements Closeable, Serializable {
 	/**
 	 * 监听是否已经关闭
 	 */
-	private boolean isClosed;
+	protected boolean isClosed;
 	/**
 	 * WatchKey 和 Path的对应表
 	 */

+ 1 - 1
hutool-core/src/test/java/cn/hutool/core/io/WatchMonitorTest.java

@@ -44,7 +44,7 @@ public class WatchMonitorTest {
 			}
 		};
 		
-		WatchMonitor monitor = WatchMonitor.createAll("d:/aaa/aaa.txt", new DelayWatcher(watcher, 500));
+		WatchMonitor monitor = WatchMonitor.createAll("d:/test/aaa.txt", new DelayWatcher(watcher, 500));
 		
 		monitor.setMaxDepth(0);
 		monitor.start();