`

Java 文件监控,实时监控文件加载

 
阅读更多

前段时间设计一个文件自动加载系统模块,功能就像是在Tomcat的webapps目录下发布war包那样,只要一有war包加载进来,tomcat立刻就会去解压这个war包,并把它挂载在tomcat上,供网络访问。

 

我这个程序的思路也正是这样,可以监控某一目录下的文件,包括文件的增加,删除,修改,正在加载,加载成功等事件,使用抽象类和接口方式来编写,要拓展此类,十分容易,当然这个也只是个人粗制滥造的一个小玩意,大有优化的空间。在JDK7.0中包含了文件监控的API,不过听说性能很不行,事件触发很不稳定,看来oracle收购了sun之后,Java前途一片渺茫啊....

 

先说说我设计的思路:启动一个不断循环的守护线程,不断检测某目录下的文件列表,并将这些文件名称和文件MD5校验码缓存起来,在下一个循环的时候直接从缓存中取出数据,进行对比,如果发现MD5校验不一样,说明文件被更新,还有文件增加,删除的事件,在代码中有相关的注释,下面开始贴代码

 

1,Monitor,这个是一个接口,开始时是设计用来做各种监控的,例如文件监控,内存监控,CPU监控,网络监控等,Monitor接口没有方法,只是一个接口标识

package cn.std.run.monitor;

public interface Monitor{

}

 

2,FileMonitor,这是一个文件监控的接口,继承Monitor,定义了文件监控的几个方法,所有有关文件监控的实现类,都必须实现此接口

package cn.std.run.monitor;


public interface FileMonitor extends Monitor ,Runnable{

	/** 文件删除 */
	void deleteAction(Object fileName);
	/** 文件增加 */
	void addAction(Object fileName);
	/** 文件更新 */
	void updateAction(Object fileName);
	/** 正在加载 */
	void isLoading(Object fileName);
	/** 加载成功 */
	void loadSuccess(Object fileName);
}

 

3,DiskFileMonitor,这是一个抽象类,实现FileMonitor接口,并对FileMonitor做了相关实现和拓展,提供给程序员后续开发的接口,程序员如果需要开发有关文件监控的相关功能,直接继承DiskFileMonitor类,就搞定

package cn.std.run.monitor;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

public abstract class DiskFileMonitor implements FileMonitor{

	private final String ServiceFilesKey = "ServiceFiles";
	private final String ServiceFilesMapKey = "ServiceFilesMapKey";
	private String filePath = "./src/cn/std/pool/cache";
	
	public DiskFileMonitor(String fpath) {
		try {
			filePath  = fpath;
			Vector<String> files = new Vector<String>();
			getFiles(files, fpath);
			CacheMgr.putCache(ServiceFilesKey,files);
			Map<String,String> hm = new HashMap<String,String>(files.size());
			for(String f:files){
				String fp = fpath+"/"+f;
				fp = fp.replaceAll("//", "/");
				try {
					String hash = HashFile.getHash(fp, "MD5");
					hm.put(f, hash);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			CacheMgr.putCache(ServiceFilesMapKey, hm);
			CacheMgr.lsCache();
			//Vector ve = (Vector)CacheMgr.getCache(ServiceFilesKey);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/** 递归获取目录下的所有文件 */
	private static void getFiles(Vector<String> ret,String fpath) throws IOException { 
        File dir = new File(fpath); 
        File[] files = dir.listFiles(); 
        
        if (files == null) 
            return; 
        for (int i = 0; i < files.length; i++) { 
            if (files[i].isDirectory()) { 
            	getFiles(ret,files[i].getAbsolutePath()); 
            } else { 
                String fileName = files[i].getName();
                ret.addElement(fileName);
            } 
        } 
    }
	
	@Override
	@SuppressWarnings("unchecked")
	public void run() {
		try {
			Vector<String> notLoadFiles = new Vector<String>();
			while(true){
				Vector<String> diskfiles = new Vector<String>();
				getFiles(diskfiles, filePath);//从磁盘中读出文件
				//判断文件是否已经加载
				Object obj = CacheMgr.getCache(ServiceFilesKey);
				Vector<String> cachefiles = null;
				if(obj instanceof Vector){
					cachefiles = (Vector<String>)obj;
				}
				if(null != cachefiles){
					int diskfilesSize = diskfiles.size();
					int cachefilesSize = cachefiles.size();
					
					//磁盘文件>缓存文件,说明磁盘中增加了文件
					if(diskfilesSize > cachefilesSize){
						Enumeration<String> diskEn = diskfiles.elements();
						while(diskEn.hasMoreElements()){
							Object diskElement = diskEn.nextElement();
							if(cachefiles.contains(diskElement)){//如果缓存中已经包含了磁盘元素,进行下一个循环
								continue;
							}else{
								notLoadFiles.addElement((String)diskElement);
							}
						}//end while 
					//磁盘中删除了文件
					}else if(diskfilesSize < cachefilesSize){
						Enumeration<String> cacheEn = cachefiles.elements();
						while(cacheEn.hasMoreElements()){
							Object cacheElement = cacheEn.nextElement();
							if(diskfiles.contains(cacheElement)){//如果缓存中已经包含了磁盘元素,进行下一个循环
								continue;
							}else{
								cachefiles.removeElement(cacheElement);
							//	System.out.println(cacheElement+" 文件删除");
								deleteAction(cacheElement);
								HashMap<String,String> upmap = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey);
								upmap.remove(cacheElement);
							}
						}//end while 
					//文件数量没有变化,分两种情况,1,删除N个文件同时又增加了N个文件。2,文件原封不动
					}else {
						Map<String,String> hm = (Map<String, String>) CacheMgr.getCache(ServiceFilesMapKey);
						Enumeration<String> diskEn = diskfiles.elements();
						Vector<Object> isIn = new Vector<Object>(diskfilesSize);
						while(diskEn.hasMoreElements()){
							Object diskElement = diskEn.nextElement();
							String diskfilepath = filePath+"/"+diskElement;
							diskfilepath = diskfilepath.replace("//", "/");
							String newhash = HashFile.getHash(diskfilepath, "MD5");
							String mapHash = hm.get(diskElement);
							if(null != mapHash){//如果不为空,说明有这个文件
								isIn.addElement(diskElement);
								if(mapHash.equals(newhash)){
									continue;
								}else{
									updateAction(diskElement);
									//更新文件hash
									HashMap<String,String> upmap = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey);
									upmap.put(diskElement.toString(),newhash);
								}
							}else{//如果为空,说明重命名了一个文件
							//	deleteAction(diskElement);
								addAction(diskElement);
								hm.put(diskElement.toString(), newhash);
								cachefiles.addElement(diskElement.toString());
								isIn.addElement(diskElement);
							} 
						}//end while
						
						List<String> willRemove = new ArrayList<String>(hm.size());
						//遍历已经存在的元素,找出被重命名的元素
						for(Map.Entry<String, String> m:hm.entrySet()){
							if(isIn.contains(m.getKey())){
								continue;
							}else{
								willRemove.add(m.getKey());
							}
						}
						
						for(String element:willRemove){
							hm.remove(element);
							cachefiles.removeElement(element);
							deleteAction(element);
						}
					}
					
					if(notLoadFiles.size() == 0){
						//服务文件没有更新
					}else{
						//服务文件更新
						
						Vector<String> loadedfiles = new Vector<String>();
						//此处加载服务文件
						for(String name:notLoadFiles){
					//		System.out.println(name+" 未加载");
							addAction(name);
					//		System.out.println(name+" 正在加载..");
							loadedfiles.addElement(name);
							isLoading(name);
					//		System.out.println(name+" 加载成功");
							cachefiles.addElement(name);
							HashMap<String, String> hm = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey);
							String path = filePath+"/"+name;
							path = path.replace("//", "/");
							hm.put(name,HashFile.getHash(path, "MD5"));
							loadSuccess(name);
							CacheMgr.lsCache();
						}
						notLoadFiles.removeAll(loadedfiles);
					}
				}
				Thread.sleep(500);
			}//end while(true)
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

 

4,MyDiskFileMonitor,这是一个测试类,程序启动之后直接监控指定目录,指定目录下如果有文件变化,MyDiskFileMonitor会马上得到调用,例如,如果增加文件,AddAction方法会被调用,参数是新增加的文件名

package cn.std.run.monitor;

public class MyDiskFileMonitor extends DiskFileMonitor{

	public MyDiskFileMonitor(String fpath) {
		super(fpath);
	}

	@Override
	public void deleteAction(Object fileName) {
		System.out.println(fileName +" 元素删除");
	}

	@Override
	public void addAction(Object fileName) {
		System.out.println(fileName +" 新增元素");
		
	}

	@Override
	public void updateAction(Object fileName) {
		System.out.println(fileName +" 元素更新");
		
	}


	@Override
	public void isLoading(Object fileName) {
		System.out.println(fileName +" 正在加载");
	}

	@Override
	public void loadSuccess(Object fileName) {
		System.out.println(fileName +" 加载成功");
	}
	
	public static void main(String[] args) {
		String filePath = "F:/monitor";
		MyDiskFileMonitor mo = new MyDiskFileMonitor(filePath);
		new Thread(mo).start();
	}
}

 

好了,运行起来看看结果:


 

 

另外,附上我自己封装的一个用来保存数据的类,暂定义是Cache,因为我开发这个实际上是准备用来做一个自己的缓存的功能的,完毕。本人欢迎骚扰,呵呵....另外,本人表示刚毕业不久,原谅我的菜,哈哈

  • 大小: 6.8 KB
分享到:
评论

相关推荐

    java文件监控例子

    Java文件监控是一个重要的功能,它允许程序实时检测文件或目录的改变,如创建、修改、删除等事件。在Java中实现文件监控,可以利用JNotify库,这是一个强大的文件系统变动通知库,支持Windows、Linux和Mac OS X操作...

    Java 服务器信息监控

    Java的`java.util.ServiceLoader`可以帮助我们发现和加载服务,而`java.lang.management.ManagementFactory`可以获取应用的运行时信息,如线程状态、类加载情况等。 为了实现一个全面的服务器监控系统,开发者还...

    web开发自动加载修改后的java文件

    总之,JRebel是Web开发中的一个强大工具,它通过实时加载修改后的Java文件,简化了开发流程,提高了开发效率。通过合理利用JRebel,开发者可以更加专注于代码编写,而不必为频繁的重启服务器而分心。

    java热加载Class文件

    Java热加载Class文件是开发者在调试和优化代码时非常实用的一种技术,它允许开发者在不重启JVM的情况下更新和替换已加载的类,极大地提高了开发效率。本文将深入探讨Java热加载Class文件的相关知识点。 首先,理解...

    java热加载Class文件.zip

    然而,通过Java热加载,开发者可以实时查看代码修改后的效果,而无需经历繁琐的重启过程。 Java热加载主要涉及到以下几个关键知识点: 1. **JRebel**: JRebel是一款知名的商业工具,它实现了Java应用的热部署功能...

    java远程监控

    Java远程监控技术是一种用于远程管理和诊断Java应用程序的方法,它允许开发者或系统管理员在不实际访问目标机器的情况下收集和分析运行时信息。在这个技术原型中,使用了Base64编码来处理图片,使得图像数据可以以...

    JAVA 文件监控 WatchService的示例方法

    JAVA 文件监控 WatchService 是 JAVA 1.7 中引入的一种文件监控机制,该机制基于操作系统的文件系统监控器,可以监控系统中所有文件的变化,而不需要遍历或比较文件。这种监控机制的效率非常高,可以实时监控文件的...

    java 远程监控程序JSN

    JSN(Java Server Monitoring)通常包括各种功能,如内存分析、线程检查、类加载器监控、JVM(Java虚拟机)指标跟踪以及对日志、错误和警告的实时查看。 **Java远程监控的基础** 1. **JMX(Java Management ...

    java 文件实时监听watchService

    在Java 7及以上版本中引入,它提供了一种有效的方式来进行实时监控,而无需频繁轮询文件系统,这极大地提高了效率,特别是在配置动态修改时,可以避免不必要的服务器重启。 `WatchService`的工作原理是通过注册对...

    javamelody监控

    - **JVM监控**:监控Java虚拟机的状态,如类加载、垃圾回收等。 - **线程监控**:查看当前应用的线程状态,查找死锁问题。 - **会话监控**:统计会话数量,监控会话超时和活动状态。 - **缓存监控**:监控各种...

    engineMonitor_java.zip_Java服务器监控_Java监控_engineMonitor_engineMoni

    针对"engineMonitor_java.zip_Java服务器监控_Java监控_engineMonitor_engineMoni"这个压缩包文件,我们可以深入探讨Java服务器监控的相关知识点,以及它如何帮助我们管理和优化Java应用。 首先,"Java服务器监控...

    java虚拟机监控

    Java虚拟机(JVM)是Java程序运行的基础,它负责执行字节码并管理应用程序的内存、线程、类加载等。为了优化和调试Java应用,监控JVM的状态至关重要。"java虚拟机监控"就是这样一个过程,通过收集和分析JVM的各项...

    java监控系统

    Java监控系统是针对Java应用程序进行性能、资源使用情况以及运行状态等进行实时监控的工具或平台。在物联网(IoT)环境中,Java监控系统尤为重要,因为它可以帮助开发者和运维人员了解设备上的Java应用运行状况,及时...

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

    2. 自动部署配置文件:使用Java实现文件监控器FileMonitor的实例代码可以实时监控配置文件的变化,并自动重新加载配置文件内容。 3. 实时监控文件变化:使用Java实现文件监控器FileMonitor的实例代码可以实时监控...

    专业java监控平台.rar

    专业java监控平台,提供以下特性: 1 JVM/OS cpu消耗监控 2 堆内存细分监控 3 非堆内存细分监控 4 GC耗时和次数监控 5 线程dump 6 堆dump 7 VM类加载及系统参数查看 8 实现了mini版本的long-polling,提供消息推送,...

    Java 运行时监控

    Java运行时监控是Java开发和运维过程中至关重要的一个环节,它可以帮助我们实时了解应用程序的运行状态,及时发现并解决问题,确保系统的稳定性和性能。本文将深入探讨Java运行时监控的相关知识点,结合提供的压缩包...

    java监控工具

    Java监控工具是用于跟踪和分析Java应用程序性能的关键组件。这些工具可以帮助开发者、系统管理员和运维人员深入了解应用程序的运行状况,及时发现并解决性能问题。在Java生态系统中,有许多优秀的监控工具,它们提供...

    Java线上监控 软件包

    一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大...

    Sigar Java实现系统监控

    本篇文章将深入探讨如何使用Sigar在Java中进行系统监控,并介绍相关的代码实现和包含的库文件。 首先,要使用Sigar进行Java系统监控,你需要下载Sigar的Java绑定包,这个包通常包含了所有必要的库文件,支持多种...

Global site tag (gtag.js) - Google Analytics