Java实时监控文件夹变化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rexueqingchun/article/details/82498519

1.配置监听器

  web项目配置监听器

  web.xml添加

<listener> 
    <listener-class>cn.com.test.InitListener</listener-class> 
</listener>

  实现ServletContextListener接口

package cn.com.test;

import java.io.File;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class InitListener implements ServletContextListener{
	 
	 @Override
	 public void contextInitialized(ServletContextEvent arg0) {
		 final File file = new File("D:\\cs");
	        new Thread(new Runnable() {
	            @Override
	            public void run() {
	                try {
	                    new WatchDir(file, true, new FileActionCallback() {
	                        @Override
	                        public void create(File file) {
	                            System.out.println("文件已创建\t" + file.getAbsolutePath());
	                        }	 
	                        @Override
	                        public void delete(File file) {
	                            System.out.println("文件已删除\t" + file.getAbsolutePath());
	                        } 
	                        @Override
	                        public void modify(File file) {
	                            System.out.println("文件已修改\t" + file.getAbsolutePath());
	                        }
	                    });
	                } catch (Exception e) {
	                    e.printStackTrace();
	                }
	            }
	        }).start();
	        System.out.println("正在监视文件夹:" + file.getAbsolutePath());
	 } 
}

  spring boot项目配置监听器

  启动类添加@WebListener注解支持

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.bind.annotation.RestController;

import cn.com.app.constant.TaskThreadPoolConfig;

@RestController
@SpringBootApplication
@EnableScheduling 		//开启定时任务支持
@EnableAsync  	  		//开启多线程异步任务支持
@ServletComponentScan   //开启对监听器@WebListener注解支持
@EnableConfigurationProperties(TaskThreadPoolConfig.class) // 开启配置属性支持
@MapperScan("cn.com.app.dao")
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

  通过@WebListener注解开启监听

import java.io.File;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class ContextListener implements ServletContextListener {

	@Override
	 public void contextInitialized(ServletContextEvent arg0) {
		 final File file = new File("D:\\cs");
	        new Thread(new Runnable() {
	            @Override
	            public void run() {
	                try {
	                    new WatchDir(file, true, new FileActionCallback() {
	                        @Override
	                        public void create(File file) {
	                            System.out.println("文件已创建\t" + file.getAbsolutePath());
	                        }	 
	                        @Override
	                        public void delete(File file) {
	                            System.out.println("文件已删除\t" + file.getAbsolutePath());
	                        } 
	                        @Override
	                        public void modify(File file) {
	                            System.out.println("文件已修改\t" + file.getAbsolutePath());
	                        }
	                    });
	                } catch (Exception e) {
	                    e.printStackTrace();
	                }
	            }
	        }).start();
	        System.out.println("正在监视文件夹:" + file.getAbsolutePath());
	 } 
}

2.创建监控文件夹核心类

import static java.nio.file.LinkOption.NOFOLLOW_LINKS;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;
 
/**
 * 文件夹监控
 */
public class WatchDir {
 
    private final WatchService watcher;
    private final Map<WatchKey, Path> keys;
    private final boolean subDir;
 
    /**
     * 构造方法
     * @param file 文件目录,不可以是文件
     */
    public WatchDir(File file, boolean subDir, FileActionCallback callback) throws Exception {
        if (!file.isDirectory())
            throw new Exception(file.getAbsolutePath() + "不是文件夹!");
 
        this.watcher = FileSystems.getDefault().newWatchService();
        this.keys = new HashMap<WatchKey, Path>();
        this.subDir = subDir;
 
        Path dir = Paths.get(file.getAbsolutePath());
 
        if (subDir) {
            registerAll(dir);
        } else {
            register(dir);
        }
        processEvents(callback);
    }
 
    @SuppressWarnings("unchecked")
    static <T> WatchEvent<T> cast(WatchEvent<?> event) {
        return (WatchEvent<T>) event;
    }
 
    /**
     * 观察指定的目录
     */
    private void register(Path dir) throws IOException {
        WatchKey key = dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
        keys.put(key, dir);
    }
 
    /**
     * 观察指定的目录,并且包括子目录
     */
    private void registerAll(final Path start) throws IOException {
        Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                register(dir);
                return FileVisitResult.CONTINUE;
            }
        });
    }
 
    /**
     * 发生文件变化的回调函数
     */
    @SuppressWarnings("rawtypes")
    void processEvents(FileActionCallback callback) {
        for (;;) {
            WatchKey key;
            try {
                key = watcher.take();
            } catch (InterruptedException x) {
                return;
            }
            Path dir = keys.get(key);
            if (dir == null) {
                System.err.println("操作未识别");
                continue;
            }
 
            for (WatchEvent<?> event : key.pollEvents()) {
                Kind kind = event.kind();
 
                // 事件可能丢失或遗弃
                if (kind == StandardWatchEventKinds.OVERFLOW) {
                    continue;
                }
 
                // 目录内的变化可能是文件或者目录
                WatchEvent<Path> ev = cast(event);
                Path name = ev.context();
                Path child = dir.resolve(name);
                File file = child.toFile();
                if (kind.name().equals("ENTRY_DELETE")) {
                    callback.delete(file);
                } else if (kind.name().equals("ENTRY_CREATE")) {
                    callback.create(file);
                } else if (kind.name().equals("ENTRY_MODIFY")) {
                    callback.modify(file);
                } else {
                    continue;
                }
 
                if (subDir && (kind == StandardWatchEventKinds.ENTRY_CREATE)) {
                    try {
                        if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
                            registerAll(child);
                        }
                    } catch (IOException x) {
                    	
                    }
                }
            }
 
            boolean valid = key.reset();
            if (!valid) {
                // 移除不可访问的目录
                // 因为有可能目录被移除,就会无法访问
                keys.remove(key);
                // 如果待监控的目录都不存在了,就中断执行
                if (keys.isEmpty()) {
                    break;
                }
            }
        }
    }
 
}

3.创建文件操作回调方法

import java.io.File;

/**
 * 文件操作的回调方法
 */
public abstract class FileActionCallback {
 
    public void delete(File file) {
    };
 
    public void modify(File file) {
    };
 
    public void create(File file) {
    };
 
}

备注:由于WatchService为jdk7添加,因此需要jdk版本为7及以上

猜你喜欢

转载自blog.csdn.net/rexueqingchun/article/details/82498519