Java實(shí)現(xiàn)文件監(jiān)控器FileMonitor的實(shí)例代碼
應(yīng)用場(chǎng)景:
代碼可以實(shí)現(xiàn)文件變化后的監(jiān)聽(tīng),如文件變化,自動(dòng)重新加載文件內(nèi)容,實(shí)現(xiàn)配置文件的熱部署。
代碼:
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
* 文件監(jiān)控器
*
* @author yx
* @date 2019/12/21 0:59
*/
public class FileMonitor {
/**
* 每2秒更新的默認(rèn)監(jiān)控器
*/
private static FileMonitor defaultFileMonitor = new FileMonitor(2 * 1000);
private Timer timer_;
private HashMap<File, FileEntry> files_; // File -> Long
private List<FileEntry> fileEntrys = new java.util.concurrent.CopyOnWriteArrayList<FileEntry>();
private Collection<WeakReference<FileListener>> 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<File, FileEntry>();
listeners_ = new ArrayList<WeakReference<FileListener>>();
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.
* <p>
* 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);
}
}
/**
* 添加監(jiān)控文件實(shí)體。
*
* @param fileEntry
*/
public void addFileEntry(FileEntry fileEntry) {
if (!fileEntrys.contains(fileEntry)) {
fileEntrys.add(fileEntry);
}
}
/**
* 通過(guò)文件實(shí)體的標(biāo)識(shí)判斷監(jiān)控文件實(shí)體是否存在。
*
* @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;
}
/**
* 通過(guò)文件實(shí)體標(biāo)識(shí)刪除一個(gè)監(jiān)控文件實(shí)體。
*
* @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<WeakReference<FileListener>> i = listeners_.iterator(); i.hasNext(); ) {
WeakReference<FileListener> 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>(fileListener));
}
/**
* Remove listener from this file monitor.
*
* @param fileListener Listener to remove.
*/
public void removeListener(FileListener fileListener) {
for (Iterator<WeakReference<FileListener>> i = listeners_.iterator(); i.hasNext(); ) {
WeakReference<FileListener> reference = (WeakReference<FileListener>) 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<FileEntry> 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("執(zhí)行文件監(jiān)控發(fā)生錯(cuò)誤:" + 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<File> files = new ArrayList<File>(files_.keySet());
for (Iterator<File> 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<WeakReference<FileListener>> j =
listeners_.iterator(); j.hasNext(); ) {
WeakReference<FileListener> reference =
(WeakReference<FileListener>) 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("執(zhí)行文件監(jiān)控發(fā)生錯(cuò)誤" + 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,那么當(dāng)文件發(fā)生變動(dòng)時(shí)只觸發(fā)指定的FileListener
*
* @author yx
* @date 2019/12/21 0:56
*/
public class FileEntry {
String id;
File file;
long lastModified;
FileListener fileListener = null;
Object userData;
WeakReference<Object> reference = null;
/**
* 構(gòu)造函數(shù)。
*
* @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<Object>(reference);
}
/**
* 構(gòu)造函數(shù)。
*
* @param id 標(biāo)識(shí)
* @param file 要監(jiān)控的文件
* @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) {
//監(jiān)控對(duì)象已經(jīng)不存在,請(qǐng)求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("執(zhí)行文件監(jiān)控事件監(jiān)聽(tīng)" + 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";
// 文件監(jiān)控
FileListener fileListener = new FileListener() {
@Override
public void fileChanged(FileEntry fileEntry) {
// TODO 文件變化后的業(yè)務(wù)處理
}
};
File file = new File(fileName);
FileEntry fileEntry = new FileEntry("database", file);
// 設(shè)置文件監(jiān)控
fileEntry.setFileListener(fileListener);
FileMonitor.getDefaultFileMonitor().addFileEntry(fileEntry);
總結(jié)
以上所述是小編給大家介紹的Java實(shí)現(xiàn)文件監(jiān)控器FileMonitor的實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)我們網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
上一篇:簡(jiǎn)單了解Spring Cloud搭建Config過(guò)程實(shí)例
欄 目:Java
本文標(biāo)題:Java實(shí)現(xiàn)文件監(jiān)控器FileMonitor的實(shí)例代碼
本文地址:http://www.jygsgssxh.com/a1/Java/8888.html
您可能感興趣的文章
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)模擬時(shí)鐘
- 01-10利用Java實(shí)現(xiàn)復(fù)制Excel工作表功能
- 01-10JavaWeb實(shí)現(xiàn)郵件發(fā)送功能
- 01-10java基于poi導(dǎo)出excel透視表代碼實(shí)例
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)數(shù)字時(shí)鐘
- 01-10基于Java驗(yàn)證jwt token代碼實(shí)例
- 01-10java實(shí)現(xiàn)液晶數(shù)字字體顯示當(dāng)前時(shí)間
- 01-10淺談Java中真的只有值傳遞么
- 01-10Java動(dòng)態(tài)顯示當(dāng)前日期和時(shí)間
- 01-10如何解決線程太多導(dǎo)致java socket連接池出現(xiàn)的問(wèn)題


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)模擬時(shí)鐘
- 01-10Springboot中@Value的使用詳解
- 01-10JavaWeb實(shí)現(xiàn)郵件發(fā)送功能
- 01-10利用Java實(shí)現(xiàn)復(fù)制Excel工作表功能
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)數(shù)字時(shí)鐘
- 01-10java基于poi導(dǎo)出excel透視表代碼實(shí)例
- 01-10java實(shí)現(xiàn)液晶數(shù)字字體顯示當(dāng)前時(shí)間
- 01-10基于Java驗(yàn)證jwt token代碼實(shí)例
- 01-10Java動(dòng)態(tài)顯示當(dāng)前日期和時(shí)間
- 01-10淺談Java中真的只有值傳遞么
隨機(jī)閱讀
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10delphi制作wav文件的方法


