+
UTF-8
diff --git a/src/main/java/com/jfinal/server/undertow/hotswap/HotSwapWatcher.java b/src/main/java/com/jfinal/server/undertow/hotswap/HotSwapWatcher.java
index 5043b7de9fb25f7191162455aac992e32c6602b1..5eeece8db8c8794298675b7bd17363a1110f2a23 100644
--- a/src/main/java/com/jfinal/server/undertow/hotswap/HotSwapWatcher.java
+++ b/src/main/java/com/jfinal/server/undertow/hotswap/HotSwapWatcher.java
@@ -1,12 +1,12 @@
/**
* Copyright (c) 2011-2021, James Zhan 詹波 (jfinal@126.com).
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -41,159 +41,159 @@ import com.jfinal.server.undertow.UndertowServer;
* 监听 class path 下 .class 文件变动,触发 UndertowServer.restart()
*/
public class HotSwapWatcher extends Thread {
-
- protected UndertowServer undertowServer;
-
- // protected int watchingInterval = 1000; // 1900 与 2000 相对灵敏
- protected int watchingInterval = 500;
-
- protected List watchingPaths;
- private WatchKey watchKey;
- protected volatile boolean running = true;
-
- public HotSwapWatcher(UndertowServer undertowServer) {
- setName("HotSwapWatcher");
- // 避免在调用 deploymentManager.stop()、undertow.stop() 后退出 JVM
- setDaemon(false);
- setPriority(Thread.MAX_PRIORITY);
-
- this.undertowServer = undertowServer;
- this.watchingPaths = buildWatchingPaths();
- }
-
- protected List buildWatchingPaths() {
- Set watchingDirSet = new HashSet<>();
- String[] classPathArray = System.getProperty("java.class.path").split(File.pathSeparator);
- for (String classPath : classPathArray) {
- buildDirs(new File(classPath.trim()), watchingDirSet);
- }
-
- List dirList = new ArrayList(watchingDirSet);
- Collections.sort(dirList);
-
- List pathList = new ArrayList(dirList.size());
- for (String dir : dirList) {
- pathList.add(Paths.get(dir));
- }
-
- return pathList;
- }
-
- private void buildDirs(File file, Set watchingDirSet) {
- if (file.isDirectory()) {
- watchingDirSet.add(file.getPath());
-
- File[] fileList = file.listFiles();
- for (File f : fileList) {
- buildDirs(f, watchingDirSet);
- }
- }
- }
-
- public void run() {
- try {
- doRun();
- } catch (Throwable e) {
- throw new RuntimeException(e);
- }
- }
-
- protected void doRun() throws IOException {
- ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
- WatchService watcher = FileSystems.getDefault().newWatchService();
- addShutdownHook(watcher);
-
- for (Path path : watchingPaths) {
- path.register(
- watcher,
- // StandardWatchEventKinds.ENTRY_DELETE,
- StandardWatchEventKinds.ENTRY_MODIFY,
- StandardWatchEventKinds.ENTRY_CREATE
- );
- }
+
+ protected UndertowServer undertowServer;
+
+ // protected int watchingInterval = 1000; // 1900 与 2000 相对灵敏
+ protected int watchingInterval = 500;
+
+ protected List watchingPaths;
+ private WatchKey watchKey;
+ protected volatile boolean running = true;
+
+ public HotSwapWatcher(UndertowServer undertowServer) {
+ setName("HotSwapWatcher");
+ // 避免在调用 deploymentManager.stop()、undertow.stop() 后退出 JVM
+ setDaemon(false);
+ setPriority(Thread.MAX_PRIORITY);
+
+ this.undertowServer = undertowServer;
+ this.watchingPaths = buildWatchingPaths();
+ }
+
+ protected List buildWatchingPaths() {
+ Set watchingDirSet = new HashSet<>();
+ String[] classPathArray = System.getProperty("java.class.path").split(File.pathSeparator);
+ for (String classPath : classPathArray) {
+ buildDirs(new File(classPath.trim()), watchingDirSet);
+ }
+
+ List dirList = new ArrayList(watchingDirSet);
+ Collections.sort(dirList);
+
+ List pathList = new ArrayList(dirList.size());
+ for (String dir : dirList) {
+ pathList.add(Paths.get(dir));
+ }
+
+ return pathList;
+ }
+
+ private void buildDirs(File file, Set watchingDirSet) {
+ if (file.isDirectory()) {
+ watchingDirSet.add(file.getPath());
+
+ File[] fileList = file.listFiles();
+ for (File f : fileList) {
+ buildDirs(f, watchingDirSet);
+ }
+ }
+ }
+
+ public void run() {
+ try {
+ doRun();
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void doRun() throws IOException {
+ ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
+ WatchService watcher = FileSystems.getDefault().newWatchService();
+ addShutdownHook(watcher);
+
+ for (Path path : watchingPaths) {
+ path.register(
+ watcher,
+ // StandardWatchEventKinds.ENTRY_DELETE,
+ StandardWatchEventKinds.ENTRY_MODIFY,
+ StandardWatchEventKinds.ENTRY_CREATE
+ );
+ }
+
+ executorService.scheduleAtFixedRate(() -> {
+ watch(watcher);
+ }, 0, 500, TimeUnit.MILLISECONDS);
// while (running) {
// watch(watcher);
// }
- executorService.scheduleAtFixedRate(() -> {
- watch(watcher);
- }, 0, 500, TimeUnit.MILLISECONDS);
- }
-
- private void watch(WatchService watcher) {
- try {
- // watchKey = watcher.poll(watchingInterval, TimeUnit.MILLISECONDS); // watcher.take(); 阻塞等待
- // 比较两种方式的灵敏性,或许 take() 方法更好,起码资源占用少,测试 windows 机器上的响应
- watchKey = watcher.take();
-
- if (watchKey == null) {
- // System.out.println(System.currentTimeMillis() / 1000);
- //continue ;
- return;
- }
- } catch (Throwable e) { // 控制台 ctrl + c 退出 JVM 时也将抛出异常
- running = false;
- if (e instanceof InterruptedException) { // 另一线程调用 hotSwapWatcher.interrupt() 抛此异常
- // while 循环没有通过 while (running && !Thread.currentThread().isInterrupted()) 控制流程,下一行代码可以不需要
- Thread.currentThread().interrupt(); // Restore the interrupted status
- }
- return;
- }
-
- List> watchEvents = watchKey.pollEvents();
- for (WatchEvent> event : watchEvents) {
- String fileName = event.context().toString();
- if (fileName.endsWith(".class")) {
- if (undertowServer.isStarted()) {
- undertowServer.restart();
- resetWatchKey();
-
- while ((watchKey = watcher.poll()) != null) {
- // System.out.println("---> poll() ");
- watchKey.pollEvents();
- resetWatchKey();
- }
-
- break;
- }
- }
- }
-
- resetWatchKey();
- }
-
- private void resetWatchKey() {
- if (watchKey != null) {
- watchKey.reset();
- watchKey = null;
- }
- }
-
- /**
- * 添加关闭钩子在 JVM 退出时关闭 WatchService
- *
- * 注意:addShutdownHook 方式添加的回调在 kill -9 pid 强制退出 JVM 时不会被调用
- * kill 不带参数 -9 时才回调
- */
- protected void addShutdownHook(WatchService watcher) {
- Runtime.getRuntime().addShutdownHook(new Thread(() -> {
- try {
- watcher.close();
- } catch (Throwable e) {
- UndertowKit.doNothing(e);
- }
- }));
- }
-
- public void exit() {
- running = false;
- try {
- this.interrupt();
- } catch (Throwable e) {
- UndertowKit.doNothing(e);
- }
- }
-
+ }
+
+ private void watch(WatchService watcher) {
+ try {
+ // watchKey = watcher.poll(watchingInterval, TimeUnit.MILLISECONDS); // watcher.take(); 阻塞等待
+ // 比较两种方式的灵敏性,或许 take() 方法更好,起码资源占用少,测试 windows 机器上的响应
+ watchKey = watcher.take();
+
+ if (watchKey == null) {
+ // System.out.println(System.currentTimeMillis() / 1000);
+ //continue ;
+ return;
+ }
+ } catch (Throwable e) { // 控制台 ctrl + c 退出 JVM 时也将抛出异常
+ running = false;
+ if (e instanceof InterruptedException) { // 另一线程调用 hotSwapWatcher.interrupt() 抛此异常
+ // while 循环没有通过 while (running && !Thread.currentThread().isInterrupted()) 控制流程,下一行代码可以不需要
+ Thread.currentThread().interrupt(); // Restore the interrupted status
+ }
+ return;
+ }
+ List> watchEvents = watchKey.pollEvents();
+ for (WatchEvent> event : watchEvents) {
+ String fileName = event.context().toString();
+ if (fileName.endsWith(".class")) {
+ if (undertowServer.isStarted()) {
+ undertowServer.restart();
+ resetWatchKey();
+
+ while ((watchKey = watcher.poll()) != null) {
+ // System.out.println("---> poll() ");
+ watchKey.pollEvents();
+ resetWatchKey();
+ }
+
+ break;
+ }
+ }
+ }
+
+ resetWatchKey();
+ }
+
+ private void resetWatchKey() {
+ if (watchKey != null) {
+ watchKey.reset();
+ watchKey = null;
+ }
+ }
+
+ /**
+ * 添加关闭钩子在 JVM 退出时关闭 WatchService
+ *
+ * 注意:addShutdownHook 方式添加的回调在 kill -9 pid 强制退出 JVM 时不会被调用
+ * kill 不带参数 -9 时才回调
+ */
+ protected void addShutdownHook(WatchService watcher) {
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ try {
+ watcher.close();
+ } catch (Throwable e) {
+ UndertowKit.doNothing(e);
+ }
+ }));
+ }
+
+ public void exit() {
+ running = false;
+ try {
+ this.interrupt();
+ } catch (Throwable e) {
+ UndertowKit.doNothing(e);
+ }
+ }
+
// public static void main(String[] args) throws InterruptedException {
// HotSwapWatcher watcher = new HotSwapWatcher(null);
// watcher.start();