`

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监控平台.rar

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

    Java线上监控 软件包

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

    Jvmm是一个同时支持操作系统监控和Java虚拟机监控的工具,提供有丰富的监控功能

    提供有丰富的监控功能:OS监控(内存状态、CPU负载、磁盘IO吞吐率、磁盘健康状态、网卡IO等)、JVM监控(内存、线程、GC、类加载器等),还提供生成火焰图、Java代码热更、反编译功能,支持以服务形式对外提供接口...

    java-虚拟机 操作系统监控工具-源码

    java监控工具源码-可集成到项目使用 内存状态、CPU负载、磁盘IO吞吐率、磁盘健康状态、网卡IO 监控 适合用于服务健康监控、线上调优、排查问题、性能测试等场景 支持操作系统监控:内存状态、CPU负载、磁盘IO及吞吐...

    JAVA上百实例源码以及开源项目

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    JAVA上百实例源码以及开源项目源代码

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    WY一款适用于Java应用的性能监控系统

    WY(Java应用监控系统)是一款基于JDK8制作,适用于Java应用,具有堆内存监控、方法区监控、GC监控、类加载监控、类编译监控与线程监控功能的在线监控系统。

    基于Java的煤矿安全监控系统通用软件的研究

    随着科技的不断发展,计算机技术广泛的应用到煤矿的生产领域当中。虽然我国煤矿资源丰富,但是地质条件极其复杂,...结合了煤矿安全监控系统的使用现状,探讨了基于Java语言动态加载技术的煤矿安全监控系统通用软件的设计。

    JavaMonitor:Java应用性能远程监控系统(使用CS架构)适用于监控所有Java应用,具有堆内存监控、方法区监控、GC监控、类加载监控、类编译监控与线程监控,提供堆快照下载,线程快照下载

    适用于监控所有Java应用,具有堆内存监控、方法区监控、GC监控、类加载监控、类编译监控与线程监控,提供堆快照下载,线程快照下载。 若使用本项目二次开发请遵守Apache开源协议,并在项目主页做上述文字说明且附上...

    JVM监控实例数 windows监控 线程测试 单例模式下测试JVM实例是否一个

    JVM监控实例数 windows监控 线程测试 单例模式下测试JVM实例是否一个

    java开源包11

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包6

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包9

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java jdk实列宝典 光盘源代码

    读写Blob数据,blob数据常以二进制形式存储比较大的文件数据,如图片、视频文件等,本文介绍如何往数据库中读写blob数据,BlobData.java; 使用ResultSet更新数据库,UpdateWithResultSet.java; 使用RowSet,....

    java开源包4

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包101

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包5

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包8

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包10

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

Global site tag (gtag.js) - Google Analytics