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

网友投稿 269 2022-12-18


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&gthttp://; 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&lthttp://;File>(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);

总结


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:JVM内存结构划分实例解析
下一篇:MyBatis执行Sql的流程实例解析
相关文章

 发表评论

暂时没有评论,来抢沙发吧~