1. 程式人生 > >Java實現系統目錄實時監聽更新。

Java實現系統目錄實時監聽更新。

warning xtend absolute ava single sdn data- sdk spl

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

Java實現系統目錄實時監聽更新。