动态加载资源文件

问题

对于java应用中的一些配置文件每次都需要重新启动服务才能重新加载,非常麻烦,故做了一个动态加载资源的程序。

可选方案

使用监听线程监听文件变化,当文件变化时通知程序重新加载配置文件,用到了事件委托模型和观察者模式类似,如下

公共部分

 

1.Listener接口

Java代码 复制代码
  1. package com.hrtc.monitor;   
  2.   
  3. /**  
  4.  * 监听器接口  
  5.  * Jul 30, 2008 3:02:28 PM  
  6.  */  
  7. public interface IMonitorListener {   
  8.     public void update(MonitorEvent event);   
  9. }  

 2.Event监听事件顶层类

Java代码 复制代码
  1. package com.hrtc.monitor;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.Iterator;   
  5. import java.util.List;   
  6.   
  7. /**  
  8.  * 监听事件  
  9.  * Jul 30, 2008 3:03:12 PM  
  10.  */  
  11. public class MonitorEvent {   
  12.     private Object lock = new Object();   
  13.     private List monitorListenerList = new ArrayList();   
  14.   
  15.     public void addListener(IMonitorListener listener) {   
  16.         synchronized (lock) {   
  17.             if (!monitorListenerList.contains(listener)) {   
  18.                 monitorListenerList.add(listener);   
  19.             }   
  20.         }   
  21.     }   
  22.   
  23.     public void removeListener(IMonitorListener listener) {   
  24.         synchronized (lock) {   
  25.             if (monitorListenerList.contains(listener)) {   
  26.                 monitorListenerList.remove(listener);   
  27.             }   
  28.         }   
  29.     }   
  30.   
  31.     public void removeAllListener() {   
  32.         synchronized (lock) {   
  33.             monitorListenerList.clear();   
  34.         }   
  35.     }   
  36.   
  37.     /**  
  38.      * 触发事件可由子类重载  
  39.      */  
  40.     public void fireEvent() {   
  41.         synchronized (lock) {   
  42.             for (Iterator it = monitorListenerList.iterator(); it.hasNext();) {   
  43.                 IMonitorListener listener = (IMonitorListener) it.next();   
  44.                 listener.update(this);   
  45.             }   
  46.         }   
  47.     }   
  48. }  

 3.主线程监听类

Java代码 复制代码
  1. package com.hrtc.monitor;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.Iterator;   
  5. import java.util.List;   
  6.   
  7. /**  
  8.  * 监听线程类  
  9.  *   
  10.  * Jul 30, 2008 3:03:55 PM  
  11.  */  
  12. public class MonitorThread extends Thread {   
  13.     private List monitorEventList = new ArrayList();   
  14.     private long interval;   
  15.     private boolean isMonitor = false;   
  16.     private Object lock = new Object();   
  17.     private static MonitorThread monitor;   
  18.   
  19.     synchronized public static MonitorThread getInstance(long intervalSecond) {   
  20.         if (monitor == null) {   
  21.             monitor = new MonitorThread(intervalSecond);   
  22.         }else{   
  23.             monitor.setInterval(intervalSecond);   
  24.         }   
  25.         return monitor;   
  26.     }   
  27.   
  28.     synchronized public static MonitorThread getInstance() {   
  29.         if (monitor == null) {   
  30.             monitor = new MonitorThread(1);   
  31.         }   
  32.         return monitor;   
  33.     }   
  34.   
  35.     /**  
  36.      * 构造方法  
  37.      *   
  38.      * @param intervalSecond  
  39.      *            监听间隔时间  
  40.      */  
  41.     public MonitorThread(long intervalSecond) {   
  42.         this.interval = intervalSecond * 1000;   
  43.     }   
  44.   
  45.     public void addEvent(MonitorEvent event) {   
  46.         synchronized (lock) {   
  47.             if (!monitorEventList.contains(event)) {   
  48.                 monitorEventList.add(event);   
  49.             }   
  50.         }   
  51.     }   
  52.   
  53.     public void removeEvent(MonitorEvent event) {   
  54.         synchronized (lock) {   
  55.             if (monitorEventList.contains(event)) {   
  56.                 monitorEventList.remove(event);   
  57.             }   
  58.         }   
  59.     }   
  60.   
  61.     public void removeAllEvent() {   
  62.         synchronized (lock) {   
  63.             monitorEventList.clear();   
  64.         }   
  65.     }   
  66.   
  67.     /**  
  68.      * 监听主方法,每隔一段间隔触发事件列表  
  69.      */  
  70.     public void run() {   
  71.         if (isMonitor) {   
  72.             return;   
  73.         }   
  74.         isMonitor = true;   
  75.         try {   
  76.             while (isMonitor) {   
  77.   
  78.                 synchronized (lock) {   
  79.                     for (Iterator it = monitorEventList.iterator(); it   
  80.                             .hasNext();) {   
  81.                         MonitorEvent event = (MonitorEvent) it.next();   
  82.                         event.fireEvent();   
  83.                     }   
  84.                 }   
  85.                 Thread.sleep(interval);   
  86.   
  87.             }   
  88.         } catch (InterruptedException e) {   
  89.             e.printStackTrace();   
  90.         } finally {   
  91.             isMonitor = false;   
  92.         }   
  93.     }   
  94.   
  95.     /**  
  96.      * 结束监听,并不是马上结束只是把标致设为结束  
  97.      */  
  98.     public void end() {   
  99.         isMonitor = false;   
  100.     }   
  101.   
  102.     /**  
  103.      * 是否正在监听  
  104.      *   
  105.      * @return  
  106.      */  
  107.     public boolean isMonitor() {   
  108.         return isMonitor;   
  109.     }   
  110.   
  111.     public long getInterval() {   
  112.         return interval;   
  113.     }   
  114.   
  115.     public void setInterval(long interval) {   
  116.         this.interval = interval;   
  117.     }   
  118.   
  119. }  

 应用案例1:可自动检查文件变化的Properties

1.首先定义一个“文件改变事件监听类”继承自MonitorEvent

Java代码 复制代码
  1. package com.hrtc.monitor.file;   
  2.   
  3. import java.io.File;   
  4. import java.io.IOException;   
  5.   
  6. import com.hrtc.monitor.MonitorEvent;   
  7.   
  8. /**  
  9.  * 文件改变监听类  
  10.  * Jul 30, 2008 3:07:05 PM  
  11.  */  
  12. public class FileChangeMonitorEvent extends MonitorEvent {   
  13.     private File f;   
  14.     private long lastModifiedTime;   
  15.     private long lastLength;   
  16.     private boolean isChanged = false;   
  17.   
  18.     /**  
  19.      *   
  20.      * @param f 需要监听的文件  
  21.      */  
  22.     public FileChangeMonitorEvent(File f) {   
  23.         if (!f.exists()) {   
  24.             try {   
  25.                 throw new IllegalArgumentException("Path "  
  26.                         + f.getCanonicalPath() + " dose't exist.");   
  27.             } catch (IOException e) {   
  28.                 e.printStackTrace();   
  29.             }   
  30.         }   
  31.         this.f = f;   
  32.         getFileInfo();   
  33.     }   
  34.   
  35.     private void getFileInfo(){   
  36.         lastModifiedTime = f.lastModified();   
  37.         lastLength = f.length();   
  38.     }   
  39.        
  40.     /**  
  41.      * 如果文件已改变则触发事件  
  42.      */  
  43.     @Override  
  44.     public void fireEvent() {   
  45.         try {   
  46.             f = f.getCanonicalFile();   
  47.             isChanged = lastModifiedTime != f.lastModified() || lastLength != f.length();   
  48.             if (isChanged) {   
  49.                 super.fireEvent();   
  50.                 getFileInfo();   
  51.                 isChanged = false;   
  52.             }   
  53.         } catch (IOException e) {   
  54.             e.printStackTrace();   
  55.         }   
  56.     }   
  57.   
  58.     /**  
  59.      * 获得监听的文件  
  60.      * @return  
  61.      */  
  62.     public File getF() {   
  63.         return f;   
  64.     }   
  65.   
  66. }  

 2.定义PropertiesEx类,以及内部类ReloadPropertiesListener

Java代码 复制代码
  1. package com.hrtc.util;   
  2.   
  3. import java.io.File;   
  4. import java.io.FileInputStream;   
  5. import java.io.FileNotFoundException;   
  6. import java.io.IOException;   
  7. import java.util.Properties;   
  8.   
  9. import com.hrtc.monitor.IMonitorListener;   
  10. import com.hrtc.monitor.MonitorEvent;   
  11. import com.hrtc.monitor.MonitorThread;   
  12. import com.hrtc.monitor.file.FileChangeMonitorEvent;   
  13.   
  14. /**  
  15.  * 可自动加载属性变化的属性类  
  16.  * Jul 30, 2008 3:10:32 PM  
  17.  */  
  18. public class PropertiesEx {   
  19.     /**  
  20.      *   
  21.      */  
  22.     private static final long serialVersionUID = -6708397622206255544L;   
  23.   
  24.     private MonitorThread monitor;   
  25.     private Properties p;   
  26.        
  27.     /**  
  28.      *   
  29.      * @param intervalSecond 监听变化间隔  
  30.      */  
  31.     public PropertiesEx(long intervalSecond) {   
  32.         monitor = MonitorThread.getInstance(intervalSecond);   
  33.     }   
  34.        
  35.     /**  
  36.      * 默认更新间隔为1s  
  37.      */  
  38.     public PropertiesEx() {   
  39.         this(1);   
  40.     }   
  41.   
  42.     /**  
  43.      * 加载配置文件  
  44.      * @param f  
  45.      * @throws FileNotFoundException  
  46.      * @throws IOException  
  47.      */  
  48.     public void load(File f) throws FileNotFoundException, IOException {   
  49.         p = new Properties();   
  50.         p.load(new FileInputStream(f));   
  51.         MonitorEvent event = new FileChangeMonitorEvent(f);   
  52.         ReloadPropertiesListener listener = new ReloadPropertiesListener();   
  53.         event.addListener(listener);   
  54.         monitor.addEvent(event);   
  55.         if(!monitor.isMonitor()){   
  56.             monitor.start();   
  57.         }   
  58.            
  59.     }   
  60.   
  61.     public String getProperty(String key){   
  62.         return p.getProperty(key);   
  63.     }   
  64.   
  65.     public Properties getProperties(){   
  66.         return p;   
  67.     }   
  68.        
  69.     /**  
  70.      * 当发生属性文件改变时重新加载属性文件<br>  
  71.      * listener为内部类,为了访问包含类中p成员变量和静止外部访问该类  
  72.      * @author xuwei  
  73.      * Jul 30, 2008 3:11:38 PM  
  74.      */  
  75.     private class ReloadPropertiesListener implements IMonitorListener {   
  76.   
  77.         public void update(MonitorEvent event) {   
  78.             FileChangeMonitorEvent fcmEvent = (FileChangeMonitorEvent) event;   
  79.             try {   
  80.                 p.load(new FileInputStream(fcmEvent.getF()));   
  81.             } catch (IOException e) {   
  82.                 throw new RuntimeException(e);   
  83.             }   
  84.         }   
  85.   
  86.     }   
  87.   
  88. }  

 3.测试类

Java代码 复制代码
  1. package com.hrtc.util;   
  2.   
  3. import java.io.File;   
  4. import java.io.FileNotFoundException;   
  5. import java.io.IOException;   
  6.   
  7. import junit.framework.TestCase;   
  8.   
  9. import com.hrtc.monitor.MonitorThread;   
  10.   
  11. public class PropertiesExTest extends TestCase {   
  12.   
  13.     protected void setUp() throws Exception {   
  14.         super.setUp();   
  15.     }   
  16.   
  17.        //测试PropertiesEx中的load方法   
  18.         public void testLoad() throws FileNotFoundException, IOException {   
  19.         System.out.println("test reload method========");   
  20.         PropertiesEx p = new PropertiesEx();   
  21.         File f = new File(PropertiesTest.class.getResource("").getPath()   
  22.                 + "test.properties");   
  23.         p.load(f);   
  24.         long t1 = System.currentTimeMillis();   
  25.         int count = 10;   
  26.         int i = 0;   
  27.         try {   
  28.                        //循环10秒,在此时间内手动修改配置文件   
  29.             while (i < count) {   
  30.   
  31.                 String name = p.getProperty("name");   
  32.                 System.out.println(i + ": name===" + name);   
  33.                 Thread.sleep(1000);   
  34.   
  35.                 i++;   
  36.             }   
  37.         } catch (InterruptedException e) {   
  38.             e.printStackTrace();   
  39.         }   
  40.         long t2 = System.currentTimeMillis();   
  41.         System.out.println(t2 - t1);   
  42.     }   
  43.        
  44.        //测试多个PropertiesEx公用同一MonitorThread   
  45.     public void testLoadMultiple() throws FileNotFoundException, IOException {   
  46.         System.out.println("test reload multiple========");   
  47.         PropertiesEx p1 = new PropertiesEx();   
  48.         File f1 = new File(PropertiesTest.class.getResource("").getPath()   
  49.                 + "test.properties");   
  50.         p1.load(f1);   
  51.         PropertiesEx p2 = new PropertiesEx();   
  52.         File f2 = new File(PropertiesTest.class.getResource("").getPath()   
  53.                 + "test1.properties");   
  54.         p2.load(f2);   
  55.         long t1 = System.currentTimeMillis();   
  56.         int count = 10;   
  57.         int i = 0;   
  58.         try {   
  59.             while (i < count) {   
  60.   
  61.                 String name = p1.getProperty("name");   
  62.                 String value = p2.getProperty("value");   
  63.                 System.out.println(i + ": " + name + "=" + value);   
  64.                 Thread.sleep(1000);   
  65.   
  66.                 i++;   
  67.             }   
  68.         } catch (InterruptedException e) {   
  69.             e.printStackTrace();   
  70.         }   
  71.         long t2 = System.currentTimeMillis();   
  72.         System.out.println(t2 - t1);   
  73.                //结束监听,清除监听事件    
  74.         MonitorThread.getInstance().end();   
  75.         MonitorThread.getInstance().removeAllEvent();   
  76.     }   
  77.   
  78. }  
 

配置文件内容,与PropertiesExTest放在同一文件夹下

test.properties

  name=name1

test1.properties

  value=value1

 

总结

上面的同一个MonitorThread甚至可以用到多个不同的事件中,比如除了Properties外还可以定义如xml等其他事件监听,而只用同一个MonitorThread。另一种方案是使用代理每次访问属性时查看文件是否修改,但是效率上比不上这种。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值