java 文件监控_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 files = new Vector();
getFiles(files, fpath);
CacheMgr.putCache(ServiceFilesKey,files);
Map hm = new HashMap(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 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 notLoadFiles = new Vector();
while(true){
Vector diskfiles = new Vector();
getFiles(diskfiles, filePath);//从磁盘中读出文件
//判断文件是否已经加载
Object obj = CacheMgr.getCache(ServiceFilesKey);
Vector cachefiles = null;
if(obj instanceof Vector){
cachefiles = (Vector)obj;
}
if(null != cachefiles){
int diskfilesSize = diskfiles.size();
int cachefilesSize = cachefiles.size();
//磁盘文件>缓存文件,说明磁盘中增加了文件
if(diskfilesSize > cachefilesSize){
Enumeration 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 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 upmap = (HashMap)CacheMgr.getCache(ServiceFilesMapKey);
upmap.remove(cacheElement);
}
}//end while
//文件数量没有变化,分两种情况,1,删除N个文件同时又增加了N个文件。2,文件原封不动
}else {
Map hm = (Map) CacheMgr.getCache(ServiceFilesMapKey);
Enumeration diskEn = diskfiles.elements();
Vector isIn = new Vector(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 upmap = (HashMap)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 willRemove = new ArrayList(hm.size());
//遍历已经存在的元素,找出被重命名的元素
for(Map.Entry 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 loadedfiles = new Vector();
//此处加载服务文件
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 hm = (HashMap)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,因为我开发这个实际上是准备用来做一个自己的缓存的功能的,完毕。本人欢迎骚扰,呵呵....另外,本人表示刚毕业不久,原谅我的菜,哈哈
java 文件监控_Java 文件监控,实时监控文件加载相关推荐
- java 启动类_java程序启动,类的加载情况
一.java程序运行的时候,不是所有类必须被加载到jvm虚拟机中才可以正常使用 是不是所有的class文件都在启动的时候全部加载呢? java中的类大致分为三种: 1.系统类 2.扩展类 3.由程序 ...
- java 爬虫 异步_Java 爬虫遇上数据异步加载,试试这两种办法!
这是 Java 爬虫系列博文的第三篇,在上一篇 Java 爬虫遇到需要登录的网站,该怎么办? 中,我们简单的讲解了爬虫时遇到登录问题的解决办法,在这篇文章中我们一起来聊一聊爬虫时遇到数据异步加载的问题 ...
- JAVA异步爬虫_Java 爬虫遇上数据异步加载,试试这两种办法!
这是 Java 爬虫系列博文的第三篇,在上一篇 Java 爬虫遇到需要登录的网站,该怎么办? 中,我们简单的讲解了爬虫时遇到登录问题的解决办法,在这篇文章中我们一起来聊一聊爬虫时遇到数据异步加载的问题 ...
- java调用驱动_Java中间件及其驱动调用、加载方法及转换装置的制造方法
Java中间件及其驱动调用.加载方法及转换装置的制造方法 [技术领域] [0001]本发明涉及移动通信技术领域,尤其涉及Java中间件及其驱动调用.加载方法及转换装置. [背景技术] [0002]Ja ...
- 0xc000000f 由于系统注册表文件丢失或损坏,因此Windows无法加载
WIN7出现以下情况,是thinkpad x61笔记本.Windows未能启动.原因可能是最近更改了硬件或软件,解决此问题的步骤: 1:插入Windows安装光盘并从新启动计算机. 2:选择语言设置, ...
- 上传文件到服务器经常连接重置,尝试将文件上传到tmp_name时,“正在加载页面时重置了”服务器的连接重置“...
我正在制作网站以将mp3文件存储在数据库中.当我访问该网站时,它说我已成功连接到数据库,并成功选择了数据库.但是当我选择一个文件并按上传按钮时,它会尝试连接很长时间,然后我的网络浏览器显示" ...
- java HelloWorld时报错:“找不到或无法加载主类“问题的解决办法
java HelloWorld时报错:"找不到或无法加载主类"问题的解决办法 参考文章: (1)java HelloWorld时报错:"找不到或无法加载主类"问 ...
- java 滚动加载数据_[Java教程]浏览器滚动条快到底部时自动加载数据
[Java教程]浏览器滚动条快到底部时自动加载数据 0 2015-11-30 15:00:44 1 2 3 4 5 6 ");24 main.append(" hello worl ...
- JDK8版本JAVA运行错误:找不到或无法加载主类 HelloJava的原因及解决方案
JDK8版本JAVA运行错误:找不到或无法加载主类 HelloJava的原因及解决方案 一.错误描述 二.编写HelloJava代码 三.在命令行CMD窗口中运行代码 四.错误原因分析 解决方案 注: ...
- python实时监控文件大小_python实现实时监控文件的方法
在业务稳定性要求比较高的情况下,运维为能及时发现问题,有时需要对应用程序的日志进行实时分析,当符合某个条件时就立刻报警,而不是被动等待出问题后去解决,比如要监控nginx的$request_time和 ...
最新文章
- maven不引入parent_Idea开发环境中,开发springboot类型的项目,如果只引入parent节点,不添加依赖节点,maven是不会加载springboot的任何依赖的...
- NLP命名实体识别(NER)代码实践
- 信号之函数的可重入性
- 【OpenCV 例程200篇】85. 频率域高通滤波器的应用
- SpringBoot指南(八)——SpringBoot整合Redis
- HDOJ水题集合4:杂题
- Dev C++调试程序方法详解
- 系统动力学软件vensim学习之lookup
- directx修复工具win7_win7蓝屏该怎么解决图文教程
- 销售系统服务器,勤哲Excel服务器-销售管理系统(9页)-原创力文档
- HTML列表、表格与媒体元素
- VS2019安装 VisualSVN Server 插件
- 数学中任意与存在符号的来历
- html5 手机模板 解放区,解放区异形模板
- 软件及操作系统的基础
- 企业邮箱如何申请?如何用手机号注册邮箱?
- 数据库系统概论(第十章数据库恢复技术)
- 计算机操作系统——学习笔记(下)
- homeassistant中通过SSH安装zerotier步骤
- 创业者必看:合伙人股权的进入机制与退出机制