Pure JS (2): 热部署 (利用 JDK 7 NIO 监控文件变化)
接着上一篇文章(
http://xxing22657-yahoo-com-cn.iteye.com/blog/1052485)的话题,我们来谈谈服务器端 JS 的热部署问题。
由于 JavaScript 是动态语言,动态编译并执行脚本并不困难。所以关键是监控文件变化。
这里推荐使用 JDK 7 NIO 中新增的 Watch Service API。Watch Service API 将尽可能使用操作系统的文件 API ,当操作系统不支持时,则使用轮询。简而言之,就是 JNI + 轮询,自己实现轮询倒不难,但要实现跨平台的 JNI 调用就很啰嗦了。
JDK 7 还没有正式发布,可以先到这里下一个 Early Access 版 :
http://jdk7.java.net/
安装完后可以通过 eclipse 的 Window -> Preference -> Java -> Intalled JREs 添加刚安装的 JRE,并勾选为默认的 JRE 环境。
关于 Watch Service API 的使用说明可以参考这里:
http://download.oracle.com/javase/tutorial/essential/io/notification.html
前期准备
首先,我们在 src 目录下创建 purejs package ,将之前编写的 JSServer,JSEngine 和 JSServlet 都移动到这个 package 下。因为后面将会用到 import static 的写法,没有 package 名称的话会报错。
然后,我们需要在 JSEngine 类中增加执行单个文件的方法( excuteFile(File file) ),并在 excuteFiles(String dir) 方法中引用它。
现在的 JSEngine 应该是这样的:
public class JSEngine {
// Declaration of engine, compliable and invocable ...
static {
// Initialize of engine, compliable and invocable ...
}
public static void excuteFiles(String dir) throws ScriptException,
IOException {
for (File file : new File(dir).listFiles()) {
excuteFile(file);
}
}
public static void excuteFile(File file) throws ScriptException,
IOException {
FileReader reader = new FileReader(file);
compliable.compile(reader).eval();
reader.close();
}
// Defination of invoke ...
}
增加文件监控类 FileChangeMonitor
实现思路是:
1. 创建一个新的线程。
2. 在线程中创建 Watch Service 的实例 watcher 。
3. 在 watcher 上注册文件的创建和修改事件。
4. 在循环中使用 watcher.take() 等待事件的发生。
5. 遍历捕捉到的所有事件,获取文件名,通知 Lisener 文件的更改。
具体实现如下:
package purejs;
import static java.nio.file.StandardWatchEventKinds.*;
import java.io.*;
import java.nio.file.*;
public class FileChangeMonitor {
public interface FileChangeListener {
public void fileChanged(File file);
}
public static void monit(final String dir,
final FileChangeListener listener) {
new Thread() {
public void run() {
Path path = new File(dir).toPath();
WatchService watcher;
try {
watcher = FileSystems.getDefault().newWatchService();
path.register(watcher, ENTRY_CREATE, ENTRY_MODIFY);
} catch (IOException e) {
e.printStackTrace();
return;
}
while (true) {
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException _) {
return;
}
processKey(path, key, listener);
}
};
}.start();
}
private static void processKey(Path path, WatchKey key,
FileChangeListener listener) {
for (WatchEvent<?> event : key.pollEvents()) {
if (event.kind() == OVERFLOW) {
continue;
}
Path fileName = (Path) event.context();
File file = path.resolve(fileName).toFile();
listener.fileChanged(file);
}
key.reset();
}
}
在 JSServer 中引入 FileChangeMonitor
将 main 函数的执行分成两个步骤:
1. 加载脚本。这里又分为两个步骤:
【执行脚本】 直接调用 JSEngine 执行“ scripts ”目录下的脚本。
【设置监控】 调用 FileChangeMonitor.monit(...),文件变更时再次执行脚本。
2. 启动 Server,与之前相同。
public class JSServer {
public static void main(String[] args) throws Exception {
loadScripts();
startServer();
}
private static void loadScripts() throws ScriptException, IOException {
JSEngine.excuteFiles("scripts");
FileChangeMonitor.monit("scripts", new FileChangeListener() {
public void fileChanged(File file) {
try {
JSEngine.excuteFile(file);
} catch (ScriptException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
// Defination of startServer() and configContext(...)
}
运行并测试
运行程序,输入
http://localhost:8080,可以看到浏览器输出:
Hello,Pei Xiaoxing!
修改 api.js ,比如改为:
api = {
sayHello: function(params) {
return 'Hello, again!';
}
};
保存修改,再次访问
http://localhost:8080,可以看到输出变化了:
Hello, again!
删除文件?
我们没有对文件删除的行为进行检查,但仍可以“曲线救国”。
比如我们不想要“ api ”这个对象了,可以把包含如下内容的文件放入 “ scripts ” :
if (typeof api !== 'undefined') {
delete api;
}
因为我们监控了文件的创建,所以这个脚本将很快被执行。这样一来,“ api ”对象就被删除了。
再次访问
http://localhost:8080 ,控制台将输出如下错误:
ReferenceError: "api" is not defined.
然后就可以把这个文件和 api.js 一起删除了。
最新版的 Java 7 中,java.nio.file.StandardWatchEventKind 已改为 java.nio.file.StandardWatchEventKinds,文章已更新。
下载附件后,请将 FileChangeMonitor.java 中的 StandardWatchEventKind 改为 StandardWatchEventKinds
分享到:
相关推荐
### JDK 7 NIO2 新特性详解 #### 引言 随着 Java 7 的发布,NIO (New I/O) 接口迎来了重要的更新,即 NIO.2 或称为 MNI (More New I/O)。NIO.2 增强了 Java 1.4 中的 NIO API,为开发人员提供了更为强大的 I/O ...
jdk7 原生的监控包含很多编程细节, 实际工作不得不处理这些复杂的细节,这里进行轻量封装 提取出fileCreated,fileModified,fileDeleted,fileRenamed等更好用的接口
在Java编程领域,JDK 7引入了一个重要的更新——NIO2.0,也被称为“New I/O 2.0”或“AIO”(Asynchronous I/O)。这个更新极大地提升了Java处理I/O操作的能力,特别是在文件系统交互和网络通信方面。NIO2.0主要增加...
shell脚本:一键部署jdk(带详细注释)
《基于JDK7的FileMonitor:精简版文件监控服务详解》 在Java开发中,对文件系统的实时监控是一项常用且重要的任务。JDK7引入了`WatchService`接口,为开发者提供了一种监听文件系统变化的能力。然而,`WatchService...
本类,是专门为了处理大文件,按行读取开发的类。 采用读文件的缓存 fbb 1024*5 行缓存 bb 256 字节 设计思想: 每次通过nio读取字节到 fbb中 然后对fbb自己中的内容进行行判断即 10 回车 13 行号 0 文件...
2. 安装 Jenkins:将 `jenkins.war` 文件部署到已配置好的 Web 服务器,例如 Tomcat 的 `webapps` 目录下。 3. 启动 Jenkins:Web 服务器会自动解压 WAR 文件并启动 Jenkins,通过浏览器访问指定的 URL(通常是 `...
5. **NIO.2文件系统API**:引入了`java.nio.file`包,提供了一套新的文件系统操作API,支持文件路径操作、文件属性查询和变更、文件观察等,相比传统的I/O操作更加强大和高效。 6. **字符串拼接优化**:JDK 7对字符...
3. **Nashorn JavaScript引擎**:JDK 7引入了一个新的JavaScript引擎,允许在Java程序中直接执行JavaScript代码。 4. **Fork/Join框架**:提供了并行计算的框架,提高多核处理器上的计算效率。 5. **文件API增强**...
7. **文件系统API(NIO.2)** 新的java.nio.file包提供了对文件系统的全面访问,包括文件、目录、符号链接和属性。API的设计更加面向对象,使得文件操作更加简洁和强大。 ### 配置环境变量 要使用这个免安装的JDK...
6. **文件系统API**:NIO.2提供了一个新的文件系统API,增强了对文件的操作,包括异步I/O和路径操作。 7. **改进的语法糖**:如动态类型和钻石操作符等,使得Java编程更简洁。 8. **并行化**:改进的并发工具,如...
为了更好地支持现代文件系统的需求,JDK 7引入了新的NIO.2 API(New I/O),该API提供了一种更为灵活的方式来处理文件路径、文件锁定以及异步文件I/O操作。 ##### 2.3 多线程编程增强 JDK 7增加了对Fork/Join框架...
centos7安装部署jdk7,全网最全面的linux环境下安装jdk的安装步骤,手把手教你一步一步安装jdk,各种细节一应俱全
在Java 7中引入的NIO.2(New IO 2.0)提供了一套全新的文件I/O API,显著地增强了对文件系统操作的支持。在这个示例中,我们将深入探讨如何使用NIO.2进行文件和目录的拷贝与移动操作。 首先,`copeOrMoveFile`方法...
1. **NIO.2(New I/O 2.0)**:JDK7引入了NIO.2,提供了一组新的文件I/O API,支持异步I/O操作,增强了文件路径处理,以及文件属性查询等功能。 2. **Path接口**:替代了旧的File类,提供了一种更抽象的方式来表示...
5. **文件系统API(NIO.2)**:引入了新的java.nio.file包,提供了更强大的文件操作功能,包括路径操作、文件属性查询以及异步I/O等。 6. **钻石运算符**:在创建匿名对象时,编译器可以自动推断出构造函数的参数...
3. **NIO.2支持**:利用Java 7的NIO.2 API,提高了连接管理和I/O处理的效率。 4. **更好的WebSocket支持**:实现了JSR 356规范,支持WebSocket通信协议。 5. **更好的管理界面**:增强了管理控制台,便于部署和管理...
6. **字符集编码**:NIO提供了更强大的字符集编码和解码功能,包括对Unicode字符集的支持,以及转换不同编码的能力。 在JDK 1.6的源码中,你可以深入理解这些概念的实现细节,例如`java.nio`包下的各种类和接口,...
在文件系统操作上,JDK7引入了`java.nio.file`包,提供了一组新的API来处理文件和目录。`Path`类代表文件系统中的路径,`Files`类提供了各种文件操作的静态方法,如读写文件、创建目录、检查文件属性等。`...