您的位置:首页 > 编程语言 > Java开发

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

2015-11-17 20:14 633 查看
本文转自:http://blog.csdn.net/chichengit/article/details/8259837

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

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

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

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

Java代码







package cn.std.run.monitor;

public interface Monitor{

}

[java] view
plaincopy

package cn.std.run.monitor;

public interface Monitor{
24000

}

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

Java代码







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);

}

[java] view
plaincopy

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类,就搞定

Java代码







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();

}

}

}

[java] view
plaincopy

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方法会被调用,参数是新增加的文件名

Java代码







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();

}

}

[java] view
plaincopy

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