分享一个文件监听器类:FileMonitor

   一直使用tomcat开发,只要将<Context docBase="MyTest" path="/MyTest" reloadable="true" /></Host>中的reloadable属性设置成true.Tomcat就能自动监测到某个文件发生了改变,然后重新装载。由于对这个有点兴趣,所有也试着写了一个简单的实现,但对于文件夹下的多个文件监测,除了把每个文件都加入监测器中外,没有更好的思路和方法。大家可以讨论一下:

 

除件有我测试的整个eclipse工程文件,有兴趣的童鞋们可以看一下.

 

FileMonitor类的代码如下所示:

 

public class FileMonitor {
	private static final FileMonitor instance = new FileMonitor();
	private Timer timer;
	private Map<String, FileMonitorTask> timerEntries;

	private FileMonitor() {
		this.timerEntries = new HashMap<String, FileMonitorTask>();
		this.timer = new Timer();
	}

	public static FileMonitor getInstance() {
		return instance;
	}

	/**
	 * 对某个文件实行监听
	 * 
	 * @param listener
	 *            The file listener
	 * @param filename
	 *            The filename to watch
	 * @param period
	 *            The watch interval.
	 */
	public void addFileChangeListener(FileChangeListener listener,

	String filename, long period) {
		this.removeFileChangeListener(filename);

		FileMonitorTask task = new FileMonitorTask(listener, filename);

		this.timerEntries.put(filename, task);
		this.timer.schedule(task, period, period);
	}

	/**
	 * 停止对某个文件的监听
	 * 
	 * @param listener
	 *            The file listener
	 * @param filename
	 *            The filename to keep watch
	 */
	public void removeFileChangeListener(String filename) {
		FileMonitorTask task = (FileMonitorTask) this.timerEntries
				.remove(filename);

		if (task != null) {
			task.cancel();
		}
	}

	private static class FileMonitorTask extends TimerTask {
		private FileChangeListener listener;
		private String filename;
		private File monitoredFile;
		private long lastModified;

		public FileMonitorTask(FileChangeListener listener, String filename) {
			this.listener = listener;
			this.filename = filename;

			this.monitoredFile = new File(filename);
			if (!this.monitoredFile.exists()) {
				return;
			}

			this.lastModified = this.monitoredFile.lastModified();
		}

		public void run() {
			long latestChange = this.monitoredFile.lastModified();
			if (this.lastModified != latestChange) {
				this.lastModified = latestChange;
				//对发生改变的文件调用处理方法
				this.listener.fileChanged(this.filename);
			}
		}
	}
}

 

当监听到文件发生改变时处理的类如下所示:

public class ClassFileChangeListener implements FileChangeListener {

	/*
	 * 当被监听的文件发生改变时,调用此方法
	 * */
	public void fileChanged(String filename) {
		System.out
				.println("File " + filename + " modified ,it must  reload  !");
	}
} 

 

当web容器启动时,将要监听的文件加入到文件监听器类中,servet类如下所示:

 

public class InitServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		// TODO Auto-generated method stub
		super.init(config);
		long period = Long.parseLong(config.getInitParameter("period"));
		String filename = config.getInitParameter("filename");
		if(period > 0 && filename != null && !filename.isEmpty()){
			//String realPath = config.getServletContext().getRealPath("");
			//String filename = realPath + "\\WEB-INF\\classes\\jdbc.propertis";
			FileMonitor.getInstance().addFileChangeListener(new ClassFileChangeListener(), filename, period);
		}
		
	}

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public InitServlet() {
		super();
		// TODO Auto-generated constructor stub
	}
}

 

 

 web.xml中的配置如下所示:

 

 

<servlet>
		<description></description>
		<display-name>InitServlet</display-name>
		<servlet-name>InitServlet</servlet-name>
		<servlet-class>servlet.InitServlet</servlet-class>
		<init-param>
			<!-- the period of watching file -->
			<param-name>period</param-name>
			<!--  milliseconds -->
			<param-value>1000</param-value>
		</init-param>
		<init-param>
			<param-name>filename</param-name>
			<param-value>D:/aa.txt</param-value>
		</init-param>
		<load-on-startup>0</load-on-startup>
	</servlet>

 由于使用eclipse开发时,eclipse中的tomcat,将文件部署在了:D:\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp3\wtpwebapps

下面,如我的这个工程中的jdbc.properties文件部署成了D:\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp3\wtpwebapps\MyTest\WEB-INF\classes\jdbc.propertis,

此时使用此路径创建的File不存在,所以为了方便测试,我将要监听的文件路径作为InitServlet的一个初始化参数了。

 

除件是整个工程的文件,直接导入eclipse中即可使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在MFC中实现 EventSink 。 (1) 在MFC中,添加ATL简单对象 CFileMonitorSink (2) 添加继承父 IDispEventImpl public IDispEventImpl (1) 0 唯一标识符, 用于区别 连接到 事件源的多个客户端 CFileMonitorSink, 当前名 _IFun1Events, COM 中的事件源接口, 包含各种事件 __ATLEventLib, COM 中Lib 具体查 MSDN --IDispEventImpl (2) 添加映射项 BEGIN_SINK_MAP(CFileMonitorSink) SINK_ENTRY_EX( 0, __uuidof(_IFun1Events), 1, OnNotify) //0 唯一标识符,用于区别 连接到 事件源的多个客户端 同上 , 1, 事件号 , 发生1号事件 由OnNotify来处理 SINK_ENTRY_EX( 0, __uuidof(_IFun1Events), 2, OnNotify2) //发生2号事件 由OnNotify2来处理 END_SINK_MAP() 并添加方法 STDMETHOD(OnNotify)(void); //事件处理 STDMETHOD(OnNotify2)(CHAR* lszContent); (3) 连接到COM中的事件容器 添加变量 CComPtr m_Object; //COM 中的事件源对象 添加方法 STDMETHOD(Start)(IUnknown* pSinkThisObject, VARIANT_BOOL* succeeded) { AFX_MANAGE_STATE(AfxGetAppModuleState()); // TODO: 在此添加实现代码 if ( DispEventAdvise(pSinkThisObject) == S_OK ) { m_Object = pSinkThisObject; *succeeded = VARIANT_TRUE; } else { *succeeded = VARIANT_FALSE; } return S_OK; } STDMETHOD(Stop)(void) //解除连接 { AFX_MANAGE_STATE(AfxGetAppModuleState()); DispEventUnadvise(m_Object); return S_OK; } 在其他中的 使用方法: CComPtr m_FileMonitorSink; CComPtr m_FileMonitor; //COM中导出接口 CoInitialize(0); HRESULT lRt = m_FileMonitorSink.CoCreateInstance( __uuidof(FileMonitorSink) ); lRt = m_FileMonitor.CoCreateInstance(__uuidof(Fun1)); //创建COM接口实例 VARIANT_BOOL succeeded; lRt = m_FileMonitorSink->Start(m_FileMonitor, &succeeded); //把 m_FileMonitorSink 连接到COM中的事件容器上 m_FileMonitor->HelloWorld(); //调用COM接口,接口中触发事件s m_FileMonitorSink->stop(); //从COM接口中解除连接 CoUninitialize(); // ################# CFileMonitorSink 代码 ################# class ATL_NO_VTABLE CFileMonitorSink : public CComObjectRootEx, public CComCoClass, public IDispatchImpl, public IDispEventImpl { public: CFileMonitorSink() { } DECLARE_REGISTRY_RESOURCEID(IDR_FILEMONITORSINK) BEGIN_COM_MAP(CFileMonitorSink) COM_INTERFACE_ENTRY(IFileMonitorSink) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() BEGIN_SINK_MAP(CFileMonitorSink) SINK_ENTRY_EX( 0, __uuidof(_IFun1Events), 1, OnNotify) SINK_ENTRY_EX( 0, __uuidof(_IFun1Events), 2, OnNotify2) END_SINK_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } CComPtr m_Object; //COM 事件源对象 public: STDMETHOD(OnNotify)(void); STDMETHOD(Stop)(void); STDMETHOD(Start)(IUnknown* pSinkThisObject, VARIANT_BOOL* succeeded); STDMETHOD(OnNotify2)(CHAR* lszContent); };

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值