Java实现文件监控器FileMonitor的实例代码

应用场景:

成都创新互联专业为企业提供云城网站建设、云城做网站、云城网站设计、云城网站制作等企业网站建设、网页设计与制作、云城企业网站模板建站服务,十年云城做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

代码可以实现文件变化后的监听,如文件变化,自动重新加载文件内容,实现配置文件的热部署。

代码: 

package com.yx.demo.filemonitor;
 
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
 
/**
 * FileMonitor
 * 文件监控器
 *
 * @author yx
 * @date 2019/12/21 0:59
 */
public class FileMonitor {
 
  /**
   * 每2秒更新的默认监控器
   */
  private static FileMonitor defaultFileMonitor = new FileMonitor(2 * 1000);
 
  private Timer timer_;
  private HashMap files_; // File -> Long
  private List fileEntrys = new java.util.concurrent.CopyOnWriteArrayList();
  private Collection> listeners_; // of WeakReference(FileListener)
 
  private long pollingInterval = 10000;
 
  public static FileMonitor getDefaultFileMonitor() {
    return defaultFileMonitor;
  }
 
  /**
   * Create a file monitor instance with specified polling interval.
   *
   * @param pollingInterval Polling interval in milli seconds.
   */
  public FileMonitor(long pollingInterval) {
    this.pollingInterval = pollingInterval;
 
    files_ = new HashMap();
    listeners_ = new ArrayList>();
 
    timer_ = new Timer("FileMonitor", true);
    timer_.schedule(new FileMonitorNotifier(), 0, pollingInterval);
  }
 
  /**
   * Stop the file monitor polling.
   */
  public void stop() {
    timer_.cancel();
    timer_ = null;
  }
 
  public void start() {
    if (timer_ == null) {
      timer_ = new Timer(true);
      timer_.schedule(new FileMonitorNotifier(), 0, pollingInterval);
    }
  }
 
  /**
   * Add file to listen for. File may be any java.io.File (including a
   * directory) and may well be a non-existing file in the case where the
   * creating of the file is to be trepped.
   * 

* More than one file can be listened for. When the specified file is * created, modified or deleted, listeners are notified. * * @param file File to listen for. */ public void addFile(String id, File file) { if (!files_.containsKey(file)) { FileEntry entry = new FileEntry(id, file, file.exists() ? file.lastModified() : -1); files_.put(file, entry); } } /** * 添加监控文件实体。 * * @param fileEntry */ public void addFileEntry(FileEntry fileEntry) { if (!fileEntrys.contains(fileEntry)) { fileEntrys.add(fileEntry); } } /** * 通过文件实体的标识判断监控文件实体是否存在。 * * @param id * @return */ public boolean fileEntryExists(String id) { if (id == null) { return false; } for (int i = 0; i < fileEntrys.size(); i++) { if (id.equals(fileEntrys.get(i).getId())) { return true; } } return false; } /** * 通过文件实体标识删除一个监控文件实体。 * * @param id */ public void removeFileEntry(String id) { if (id == null) { return; } for (int i = 0; i < fileEntrys.size(); i++) { if (id.equals(fileEntrys.get(i).getId())) { fileEntrys.remove(i); return; } } } /** * Remove specified file for listening. * * @param file File to remove. */ public void removeFile(File file) { files_.remove(file); } /** * Add listener to this file monitor. * * @param fileListener Listener to add. */ public void addListener(FileListener fileListener) { // Don't add if its already there for (Iterator> i = listeners_.iterator(); i.hasNext(); ) { WeakReference reference = i.next(); FileListener listener = (FileListener) reference.get(); if (listener == fileListener) { return; } } // Use WeakReference to avoid memory leak if this becomes the // sole reference to the object. listeners_.add(new WeakReference(fileListener)); } /** * Remove listener from this file monitor. * * @param fileListener Listener to remove. */ public void removeListener(FileListener fileListener) { for (Iterator> i = listeners_.iterator(); i.hasNext(); ) { WeakReference reference = (WeakReference) i.next(); FileListener listener = (FileListener) reference.get(); if (listener == fileListener) { i.remove(); break; } } } /** * This is the timer thread which is executed every n milliseconds according * to the setting of the file monitor. It investigates the file in question * and notify listeners if changed. */ private class FileMonitorNotifier extends TimerTask { @Override public void run() { try { for (Iterator i = fileEntrys.iterator(); i.hasNext(); ) { try { FileEntry entry = i.next(); if (entry == null || !entry.check()) { i.remove(); } } catch (Throwable t) { t.printStackTrace(); System.out.println("执行文件监控发生错误:" + t.getMessage()); } } // Loop over the registered files and see which have changed. // Use a copy of the list in case listener wants to alter the // list within its fileChanged method. Collection files = new ArrayList(files_.keySet()); for (Iterator i = files.iterator(); i.hasNext(); ) { File file = i.next(); try { FileEntry fileEntry = files_.get(file); long lastModifiedTime = fileEntry.getLastModified(); long newModifiedTime = file.exists() ? file.lastModified() : -1; //logger.debug(file.getAbsolutePath()); //logger.debug(" {}=>{}", lastModifiedTime, newModifiedTime); // Chek if file has changed if (newModifiedTime != lastModifiedTime) { //logger.debug("file changed {})", file.getAbsolutePath()); fileEntry.setLastModified(newModifiedTime); // Register new modified time files_.put(file, fileEntry); if (fileEntry.getFileListener() != null) { fileEntry.getFileListener().fileChanged(fileEntry); } else { // Notify listeners for (Iterator> j = listeners_.iterator(); j.hasNext(); ) { WeakReference reference = (WeakReference) j.next(); FileListener listener = (FileListener) reference.get(); // Remove from list if the back-end object has been GC'd if (listener == null) { j.remove(); } else { listener.fileChanged(fileEntry); } } } } } catch (Throwable t) { if (file != null) { t.printStackTrace(); System.out.println( "file monitor execute error, file=" + file.getAbsolutePath() + t.getMessage()); } else { System.out.println( "file monitor execute error, file=null" + t.getMessage()); } } } } catch (Throwable t) { System.out.println("执行文件监控发生错误" + t.getMessage()); } } } } package com.yx.demo.filemonitor; /** * FileListener * * @author yx * @date 2019/12/21 0:55 */ public interface FileListener { /** * * @param fileEntry */ public void fileChanged(FileEntry fileEntry); }

package com.yx.demo.filemonitor; 

import java.io.File;
import java.lang.ref.WeakReference;
/**
 * FileEntry
 * 文件Entry,如果FileEntry指定了FileListener,那么当文件发生变动时只触发指定的FileListener
 *
 * @author yx
 * @date 2019/12/21 0:56
 */
public class FileEntry {
  String id;
  File file;
  long lastModified;
  FileListener fileListener = null;
  Object userData;
  WeakReference reference = null;
  /**
   * 构造函数。
   *
   * @param id
   * @param file
   */
  public FileEntry(String id, File file) {
    this(id, file, file.exists() ? file.lastModified() : -1);
  }
  public FileEntry(Object reference, String id, File file) {
    this(id, file, file.exists() ? file.lastModified() : -1);
    reference = new WeakReference(reference);
  }
  /**
   * 构造函数。
   *
   * @param id      标识
   * @param file     要监控的文件
   * @param lastmodified 最后修改日期
   */
  public FileEntry(String id, File file, long lastmodified) {
    super();
    this.id = id;
    this.file = file;
    this.lastModified = lastmodified;
  }
  public boolean check() {
    if (reference != null && reference.get() == null) {
      //监控对象已经不存在,请求FileMonitor删除自己
      return false;
    }
    long newModifiedTime = file.exists() ? file.lastModified() : -1;
    if (lastModified != newModifiedTime) {
      this.lastModified = newModifiedTime;
      FileListener ls = this.getFileListener();
      if (ls == null) {
        return false;
      } else {
        try {
          ls.fileChanged(this);
        } catch (Exception e) {
          e.printStackTrace();
          System.err.println("执行文件监控事件监听" + e.getMessage());
        }
        return true;
      }
    } else {
      return true;
    }
  }
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public File getFile() {
    return file;
  }
  public void setFile(File file) {
    this.file = file;
  }
  public long getLastModified() {
    return lastModified;
  }
  public void setLastModified(long lastModified) {
    this.lastModified = lastModified;
  }
  public FileListener getFileListener() {
    return fileListener;
  }
  public void setFileListener(FileListener fileListener) {
    this.fileListener = fileListener;
  }
  public Object getUserData() {
    return userData;
  }
  public void setUserData(Object userData) {
    this.userData = userData;
  }
}

使用demo:

// 文件路径
String fileName = "conf/database.xml";
// 文件监控
FileListener fileListener = new FileListener() {
@Override
public void fileChanged(FileEntry fileEntry) {
// TODO 文件变化后的业务处理
}
};
File file = new File(fileName);
FileEntry fileEntry = new FileEntry("database", file);
// 设置文件监控
fileEntry.setFileListener(fileListener);
FileMonitor.getDefaultFileMonitor().addFileEntry(fileEntry);

总结

以上所述是小编给大家介绍的Java实现文件监控器FileMonitor的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对创新互联网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!


当前文章:Java实现文件监控器FileMonitor的实例代码
分享链接:http://pwwzsj.com/article/poiphd.html