论坛首页 Java企业应用论坛

Java自动重载Spring配置文件

浏览 13360 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (1)
作者 正文
   发表时间:2011-06-21  
系统中有些配置文件,修改后需要重启应用,这很让人苦恼,也很无奈,谁叫他只加载一次。
下面涉及动态加载配置文件。
需求如下:
         “如果配置文件有改动,自动加载配置文件,重配Spring加载”
需要监控目录下的文件是否变更,可以设置监控间隔时间,比如我这配置发上去,1分钟后自动生效,具体的生效时间可自定义.
代码如下,借助commons-io.jar,毕竟重复造轮子不是我的最爱.
package com.ycl.filter.FileCleaner;

import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;

/**
 * 监控类.
 * @author yangchunlong.tw
 *
 */
public class FileMonitor {

	FileAlterationMonitor monitor = null;

	/**
	 * 默认10妙看一次
	 * @param ob
	 */
	public FileMonitor(FileAlterationObserver ob){
		this(10000,ob);
	}

	/**
	 * 每隔多少时候看一次,观察者
	 * @param fileName
	 * @param ob
	 */
	public FileMonitor(long interval,FileAlterationObserver ob){
		monitor = new FileAlterationMonitor(interval,new FileAlterationObserver[]{ob});
	}

	/**
	 * 添加观察者
	 * @param observer
	 */
	public void addObserver(FileAlterationObserver observer){
		monitor.addObserver(observer);
	}

	/**
	 * 移除观察者
	 * @param observer
	 */
	public void removeObserver(FileAlterationObserver observer){
		monitor.removeObserver(observer);
	}

	/**
	 * 获取所有观察者
	 * @return
	 */
	public Iterable<FileAlterationObserver> getObservers() {
		return monitor.getObservers();
	}

	/**
	 * 启动监控[observer.initialize()]
	 */
	public void start(){
		try {
			monitor.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 停止监控[observer.destroy()]
	 */
	public void stop(){
		try {
			monitor.stop();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * [不做调用]
	 * 具体的监控操作:
	 *     observer.checkAndNotify()
	 */
	private void run(){
		monitor.run();
	}


}


以上是文件监控类,其中涉及到观察者,观察者如下:
package com.ycl.filter.FileCleaner;

import java.io.File;
import java.io.FileFilter;

import org.apache.commons.io.IOCase;
import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationObserver;

public class FileObserver extends FileAlterationObserver{

	private static final long serialVersionUID = 3637219592248717850L;

	/**
	 * 设置观查的文件对象/路径对象
	 * @param directory
	 */
	public FileObserver(String directory) {
		this(new File(directory),(FileFilter)null);
	}

	/**
	 * 设置观查的文件路径,带文件过滤器,比如所有xml文件.
	 *     这里的IOCase是设置文件比较器(排序).[根据系统,可以不用理会]
	 * @param directoryName
	 * @param fileFilter
	 */
	public FileObserver(File fileName, FileFilter fileFilter){
		super(fileName,fileFilter,(IOCase)null);
	}

	/**
	 * 监控启动时初始化方法
	 *   1. 刷新本文件对象
	 *   2. 得到本文件列表
	 *   3. 循环初始化File实体
	 *   4. 设置本文件以及其下的上下级关系
	 */
	 public void initialize() throws Exception {
		super.initialize();
	 }

	 /**
	  * 停止监控
	  * 	默认啥都没做
	  */
	 public void destroy() throws Exception {
		 super.destroy();
	 }


	 /**
	  * 监测文件有没有创建,修改,删除
	  *        并触发相应监听
	  *        如果文件名称比原先的大,那么创建一个实体,并调用onDirectoryCreate/onFileCreate
	  *        如果文件名称比原先的小,那么删除一个实体,并调用onDirectoryDelete/onFileDelete
	  *        如果文件名称和原告的一样,新的文件与原先的文件进行对比,如果文件属性有改变,并调用onDirectoryChange/onFileChange,循环调用自身,可能是文件夹
	  *        如果名称长度排在之后,添加文件,并调用onDirectoryCreate/onFileCreate
	  * 这样就注册了所有文件的监听器
	  */
	 public void checkAndNotify() {
		 super.checkAndNotify();
	 }

	 /**
	  * 添加监听器
	  */
	 public void addListener(final FileAlterationListener listener) {
		 super.addListener(listener);
	 }

	 /**
	  * 移除监听器
	  */
	 public void removeListener(final FileAlterationListener listener) {
		 super.removeListener(listener);
	 }


	 /**
	  * 获取观察者对象的所有监听器
	  */
	 public Iterable<FileAlterationListener> getListeners() {
		 return super.getListeners();
	 }

}


在观察者当中涉及到监听者,比如当文件变化了,有个监听者去执行相应的逻辑,比如重新加载Spring配置文件.
package com.ycl.filter.FileCleaner;

import java.io.File;

import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationObserver;

public class FileListener extends FileAlterationListenerAdaptor{

	@Override
	public void onDirectoryChange(File directory) {
		System.out.println("文件目录变更了:"+directory.getAbsolutePath());
	}

	@Override
	public void onDirectoryCreate(File directory) {
		System.out.println("文件目录创建了:"+directory.getAbsolutePath());
	}

	@Override
	public void onDirectoryDelete(File directory) {
		System.out.println("文件目录删除了:"+directory.getAbsolutePath());
	}

	@Override
	public void onFileChange(File file) {
		System.out.println("文件变更了:"+file.getAbsolutePath());
	}

	@Override
	public void onFileCreate(File file) {
		System.out.println("文件创建了:"+file.getAbsolutePath());
	}

	@Override
	public void onFileDelete(File file) {
		System.out.println("文件删除了:"+file.getAbsolutePath());
	}

	@Override
	public void onStart(FileAlterationObserver observer) {
		System.out.println("开始监听:"+observer.getDirectory());
	}

	@Override
	public void onStop(FileAlterationObserver observer) {
		System.out.println("停止监听:"+observer.getDirectory());
	}

}


万事俱备了,以下是测试代码:
package com.ycl.filter.FileCleaner;

public class TestFileMonitor {

	public static void main(String args[]){
		FileObserver ob = new FileObserver("D:\\test");
		FileListener listener = new FileListener();
		ob.addListener(listener);
		FileMonitor monitor = new FileMonitor(ob);
		monitor.start();
	}
}


监听某个目录下的文件,如果不需要监听,可以调用stop()方法。比如我可以在配置里面设置这个参数来控制是否需要动态加载Spring配置文件.
测试结果如下:
...
文件目录创建了:D:\test\bbb
停止监听:D:\test
开始监听:D:\test
文件目录删除了:D:\test\bbb
文件目录创建了:D:\test\新建文件夹
停止监听:D:\test
开始监听:D:\test
文件目录创建了:D:\test\cccc
文件目录删除了:D:\test\新建文件夹
停止监听:D:\test
开始监听:D:\test
文件创建了:D:\test\cccc\新建 文本文档.txt
停止监听:D:\test
开始监听:D:\test
文件创建了:D:\test\cccc\abc.test
文件删除了:D:\test\cccc\新建 文本文档.txt
停止监听:D:\test
开始监听:D:\test
文件删除了:D:\test\cccc\abc.test
文件目录删除了:D:\test\cccc
停止监听:D:\test

可以返复操作此目录下的文件或者文件夹,这里都能监听到此目录下文件的变化.
   发表时间:2011-06-22  
lz,你这种方式理论上可行!但是考虑到服务器资源有点不合实际。
0 请登录后投票
   发表时间:2011-06-22  
xinkgf 写道
lz,你这种方式理论上可行!但是考虑到服务器资源有点不合实际。

这个看需求了,一般监控配置文件不大会有问题,100个配置文件撑死了,我一个线程每隔1分钟跑一次,应该没有问题。
这位仁兄为什么会提出这个疑问.
0 请登录后投票
   发表时间:2011-06-22  
正在处理业务,你重新加载了配置文件怎么办?
1 请登录后投票
   发表时间:2011-06-22  
在生产环境修改配置文件,正确性什么的都要保证。
0 请登录后投票
   发表时间:2011-06-22   最后修改:2011-06-22
生产环境的应该不需要热加载,只要做到开发环境热加载就可以了。生产环境务必关闭该机制。
0 请登录后投票
   发表时间:2011-06-23  
脱离需求啊,有什么场景会边跑边改spring配置文件吗?
0 请登录后投票
   发表时间:2011-06-23  
yin_bp 写道
生产环境的应该不需要热加载,只要做到开发环境热加载就可以了。生产环境务必关闭该机制。

支持
0 请登录后投票
   发表时间:2011-06-23  
没看明白,和Spring有关
0 请登录后投票
   发表时间:2011-06-23  
楼主可以看看jrebel是不是你需要的
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics