zoukankan      html  css  js  c++  java
  • Java实现系统目录实时监听更新。

     

      SDK1.7新增的nio WatchService能完美解决这个问题。美中不足是如果部署在window系统下会出现莫名其妙的文件夹占用异常导致子目录监听失效,linux下则完美运行。这个问题着实让人头疼。如果有童鞋找到问题根源请一起探讨。

      这里简单的列出用Servlet实现的基本类供大家参考。首先是核心的实现类。

      

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
     110
     111
     112
     113
     114
     115
     116
     117
     118
     119
     120
     121
     122
     123
     124
     125
     126
     127
     128
     129
     130
     131
     132
     133
     134
     135
     136
     137
     138
     139
     140
     141
     142
     143
     144
     145
     146
     147
     148
    package com.event;
     
    import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
    import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
    import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
    import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
     
    import java.io.File;
    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.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Observable;
    import java.util.concurrent.Executor;
    import java.util.concurrent.Executors;
    import java.util.concurrent.FutureTask;
     
    import org.apache.poi.ss.formula.ptg.Ptg;
     
    public class DirectoryWatcher extends Observable {
    // 存储监听主键和监听目录的对应
    private static Map<WatchKey, String> pathMap = null;
    private WatchService watcher;// 目录监听服务
    private WatchKey key;// 目录对应的监听key
    private Executor executor = Executors.newSingleThreadExecutor();
    FutureTask<Integer> task = new FutureTask<Integer>(() -> {
    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();
    pathMap = new HashMap<WatchKey, String>();
    registDirs(dir);
    }
     
    private void registDirs(String dir) throws IOException {
    List<File> dirs = new ArrayList<File>();
    File dirRoot = new File(dir);
    getAllDirs(dirRoot, dirs);
    // 循环路径下所有目录填充map
    for (File eveDir : dirs) {
    Path path = Paths.get(eveDir.getAbsolutePath());
    // 监控目录内文件的更新、创建和删除事件
    try {
    key = path.register(watcher, ENTRY_CREATE, ENTRY_DELETE);
    pathMap.put(key, eveDir.getAbsolutePath());
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
     
    // 递归获取所有目录
    private void getAllDirs(File dir, List<File> dirs) {
    if (dir.isDirectory()) {
    dirs.add(dir);
    File[] fs = dir.listFiles();
    for (File f : fs) {
    getAllDirs(f, dirs);
    }
    }
    }
     
    /**
    * 启动监控过程
    */
    public void execute() {
    // 通过线程池启动一个额外的线程加载Watching过程
    executor.execute(task);
    }
     
    /**
    * 关闭后的对象无法重新启动
    */
    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();
    if (kind == OVERFLOW) {
    continue;
    }
    WatchEvent<Path> ev = cast(event);
     
    Path name = ev.context();
    String fileName = name.getFileName().toString();
    String dirPath = pathMap.get(signal) + "/" + fileName;
    if (kind.name().equals("ENTRY_CREATE")
    && fileName.indexOf(".") == -1) {
    Path path = Paths.get(dirPath);
    try {
    key = path
    .register(watcher, ENTRY_CREATE, ENTRY_DELETE);
    pathMap.put(key, dirPath);
    } catch (IOException e) {
    e.printStackTrace();
    }
    } else if (kind.name().equals("ENTRY_DELETE")
    && fileName.indexOf(".") == -1) {
    pathMap.remove(key);
    key.cancel();
    }
     
    System.out.println("event:" + kind.name() + ";file:" + dirPath);
    FileWatchEventArgs args = new FileWatchEventArgs(kind.name(),
    pathMap.get(signal), fileName);
    notifiy(args);// 通知所有观察者事件变更
    }
    // 为监控下一个通知做准备
    signal.reset();
    }
    }
     
    // * 通知外部各个Observer目录有新的事件更新
    void notifiy(FileWatchEventArgs args) {
    // 标注目录已经被做了更改
    setChanged();
    // 主动通知各个观察者目标对象状态的变更
    notifyObservers(args);
    }
    }
     来自CODE的代码片
    DirectoryWatcher.java


      Servlet的实现类:
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
     110
     111
     112
     113
     114
     115
     116
     117
     118
     119
     120
     121
     122
     123
     124
     125
     126
     127
     128
     129
     130
     131
    package com.demo;
     
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Observable;
    import java.util.Observer;
     
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    import com.entry.VedioFile;
    import com.event.DirectoryWatcher;
    import com.event.FileWatchEventArgs;
     
    public class GetList extends HttpServlet implements Observer {
     
    private static final long serialVersionUID = 3715567236188574915L;
    private String PATH;
    private String JsonTreeStr = null;
    private static List<VedioFile> vedioFileList;
    private static ThreadLocal<String> SubRequestURL = new ThreadLocal<String>();
     
    public static ThreadLocal<String> getSubRequestURL() {
    return SubRequestURL;
    }
     
    public static List<VedioFile> getVedioFileList() {
    return vedioFileList;
    }
     
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    PATH = request.getServletContext().getRealPath("/") + "/curse";
     
    request.getRequestDispatcher("/WEB-INF/index.jsp").forward(request,
    response);
    }
     
    public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    if (vedioFileList == null) {
    PATH = request.getServletContext().getRealPath("/") + "curse";
    System.out.println(PATH);
    setVedioFileList();
    // 建立目录监听,注册观察者为本身
    DirectoryWatcher dw = new DirectoryWatcher(PATH);
    dw.addObserver(this);
    dw.execute();
    }
     
    SubRequestURL
    .set(request.getRequestURL().toString().split("getList")[0]);
    JsonTreeStr = vedioFileList.toString();
    response.setContentType("text/xml;charset=utf-8");
    response.setHeader("Cache-Control", "no-cache");
    response.getWriter().write(JsonTreeStr);
    }
     
    @Override
    // 实现Observer观察者接口,接收通知
    public void update(Observable o, Object arg) {
    FileWatchEventArgs args = (FileWatchEventArgs) arg;
     
    String name = args.getName();
    String kind = args.getKind();
    String dir = args.getDir();
     
    File file = new File(dir + File.separator + name);
    if (kind.equals("ENTRY_CREATE")) {
    addVedioFile(file);
    } else if (kind.equals("ENTRY_DELETE")) {
    removeVedioFile(file);
    }
     
    }
     
    private void removeVedioFile(File file) {
    VedioFile nowVf = getNowVedioFile(file);
    if (nowVf != null) {
    for (int i = vedioFileList.size() - 1; i >= 0; i--) {
    if (nowVf.getPath()
    .equals(vedioFileList.get(i).getParentPath())) {
    vedioFileList.remove(i);
    }
    }
    vedioFileList.remove(nowVf);
    }
    }
     
    private VedioFile getNowVedioFile(File file) {
    VedioFile nowVf = null;
    for (VedioFile vf : vedioFileList) {
    if (file.getAbsolutePath().equals(vf.getPath())) {
    nowVf = vf;
    break;
    }
    }
    return nowVf;
    }
     
    private void setVedioFileList() {
    File file = new File(PATH);
    vedioFileList = new ArrayList<VedioFile>();
    getVedioFiles(file, vedioFileList);
    }
     
    private void getVedioFiles(File file, List<VedioFile> vfs) {
    if (file.isDirectory()) {
    File[] files = file.listFiles();
    for (File f : files) {
    getVedioFiles(f, vfs);
    }
    }
    addVedioFile(file);
    }
     
    private void addVedioFile(File file) {
    VedioFile vf = new VedioFile();
    vf.setParentPath(file.getParent());
    vf.setPath(file.getAbsolutePath());
    vf.setName(file.getName());
    if (file.getName().toLowerCase().endsWith(".mp4")) {
    vf.setUrl("vedio?url=" + MD5Utils.md5(vf.getPath()));
    }
    vedioFileList.add(vf);
    }
    }
     来自CODE的代码片
    GetList.java

     转:http://blog.csdn.net/feiying2j/article/details/50719648
    附上源码下载地址:
    http://download.csdn.net/detail/feiying2j/9439698
  • 相关阅读:
    前端vscode比较好用的保存自动格式化settings.json配置
    jvm 调优
    ElasticSearch CPU和内存占用高的优化记录
    nginx 安装部署
    Windows 下Redis的部署 及key 过期事件
    Docker 部署应用过程记录
    实现鼠标悬停,div勾画div边框的动画
    html+jquery实现简单图片裁剪
    css+jquery 实现图片局部放大预览
    flex 布局 实现电商网页菜单的多级分类展示
  • 原文地址:https://www.cnblogs.com/hd-zg/p/6905066.html
Copyright © 2011-2022 走看看