通过Java SE 7自带的监控服务实现类似.NET FileWatcher的功能 (一)

2014-11-24 01:45:26 · 作者: · 浏览: 0

Java SE 7 Tutorial中增加了一个监控目录变更情况的示例,用于介绍其新发布的WatchService API。

但对于用惯了.NET FileWatcher的用户而言,如果用于项目我认为它有两个欠缺:

1、应该提供一个独立线程后台运行机制,让这个监控过程自己在后台转,不影响前端处理

2、Java不像.NET有内置的源生事件机制,不过可以借助它内置的Observer/Observable对象用观察者模式实现准事件

下面是把Java SE Tutorial示例中无关内容删除,补充上述两个扩展后的实现,因为这个API比较新,也希望能和大家多多探讨:

1、参考.NET定义事件参数对象

package marvellousworks.practicalpattern.concept.unittest;

import java.nio.file.WatchEvent.Kind;

/**

* 文件系统事件类型

* @author wangxiang

*

*/

public final class FileSystemEventArgs {

private final String fileName;

private final Kind< > kind;

public FileSystemEventArgs(String fileName, Kind< > kind){

this.fileName = fileName;

this.kind = kind;

}

/**

* 文件的路径

*/

public String getFileName(){return fileName;}

/**

* 操作类型:变更、创建、删除

*/

@SuppressWarnings("rawtypes")

public Kind getKind(){return kind;}

}

2、定义DirectoryWatcher,用于监控某个文件夹,至于如何扩展FileWatcher则可以在这个基础上通过限定文件名称和操作类型的方式扩展

package marvellousworks.practicalpattern.concept.unittest;

import java.io.IOException;

import java.nio.file.FileSystems;

import java.nio.file.Path;

import java.nio.file.Paths;

import java.nio.file.WatchEvent;

import java.nio.file.WatchEvent.Kind;

import java.nio.file.WatchKey;

import java.nio.file.WatchService;

import java.util.Observable;

import java.util.concurrent.Callable;

import java.util.concurrent.Executor;

import java.util.concurrent.Executors;

import java.util.concurrent.FutureTask;

import static java.nio.file.StandardWatchEventKinds.*;

/**

* 监控一个目录内文件的更新、创建和删除事件(不包括子目录)

*

* 对于http://download.oracle.com/javase/tutorial/essential/io/notification.html进行了改造

* 使其更接近.NET的DirectoryWatcher使用习惯

*

* 由于java没有类似.NET源生的事件机制

* 因此实现上采用了Java SE自带的Observer/Observable对象对外抛出“假”事件

*

* 适于Java SE 7

*

* @author wangxiang

*

*/

public class DirectoryWatcher extends Observable{

private WatchService watcher;

private Path path;

private WatchKey key;

private Executor executor = Executors.newSingleThreadExecutor();

FutureTask task = new FutureTask(

new Callable(){

public Integer call() throws InterruptedException{

processEvents();

return Integer.valueOf(0);}});

@SuppressWarnings("unchecked")

static WatchEvent cast(WatchEvent< > event) {

return (WatchEvent) event;

}

public DirectoryWatcher(String dir) throws IOException {

watcher = FileSystems.getDefault().newWatchService();

path = Paths.get(dir);

// 监控目录内文件的更新、创建和删除事件

key = path.register(watcher, ENTRY_MODIFY, ENTRY_CREATE, ENTRY_DELETE);

}

/**

* 启动监控过程

*/

public void execute(){

// 通过线程池启动一个额外的线程加载Watching过程

executor.execute(task);

}

/**

* 关闭后的对象无法重新启动

* @throws IOException

*/

public void shutdown() throws IOException {

watcher.close();

executor = null;

}

/**

* 监控文件系统事件

*/

void processEvents() {

while (true) {

// 等待直到获得事件信号

WatchKey signal;

try {

signal = watcher.take();

} c