当前位置:编程学习 > JAVA >>

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

 

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<Integer> task = new FutureTask<Integer>(

            new Callable<Integer>(){

                public Integer call() throws InterruptedException{

                    processEvents();

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

 

    @SuppressWarnings("unchecked")

    static <T> WatchEvent<T> cast(WatchEvent<?> event) {

        return (WatchEvent<T>) 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();

            } catch (InterruptedException x) {

                return;

            }

 

            for (WatchEvent<?> event : signal.pollEvents()) {

                Kind<?> kind = event.kind();

 

                // TBD - provide example of how OVERFLOW event is handled

                if (kind == OVERFLOW) {

                    continue;

         

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,