log4j 支持運行時修改日志的相關配置,看了一下他的source code, 用FileWatchdog這個類來做的,代碼也很簡單,通過循環在一定時間間隔讀取配置文件,如果文件變更,調用一個doOnChange()方法。
如果自己要做一個支持運行時修改配置的系統可參考上面的做法。
下面是一段支持運行時修改配置的系統Prototype代碼,和log4j的做法稍有不同,使用Observer模式,使其更加靈活。
如果某個類要在系統配置修改時得到通知,則這個類要實現Observer接口,然后調用ConfigManager.getInstance().addObserver(this);
在void update(Observable o, Object args)方法里處理相應的屬性即可。
import?java.io.File;
import?java.io.FileInputStream;
import?java.io.FileOutputStream;
import?java.io.IOException;
import?java.io.InputStream;
import?java.io.OutputStream;
import?java.util.Observable;
import?java.util.Properties;

import?org.apache.log4j.Logger;

import?cn.heapstack.realtimeconfig.exception.ShutdownFailureException;
import?cn.heapstack.realtimeconfig.exception.StartupFailureException;
import?cn.heapstack.realtimeconfig.util.FileResolver;


/**?*//**
?*?<p>
?*?This?class?holds?all?configuration?for?the?system.?The?configuration?parameters
?*?are?read?from?file?at?configurable?interval.?
?*?
?*?This?class?implements?the?Singleton?pattern.
?*?
?*?Because?this?class?extends?the?<code>Observable</code>?class,?an
?*?<code>Observer</code>?may?register?and?get?notified?when?the?configuration
?*?has?changed.
?*?</p>
?*
?*/
public?final?class?DemoConfigManager?extends?Observable?implements?Runnable


{
????private?static?DemoConfigManager?myInstance?=?new?DemoConfigManager();

????private?final?String?myName?=?"ConfigManager";

????private?static?final?Logger?myLog?=?Logger.getLogger(DemoConfigManager.class);;

????private?File?configFile?=?null;

????private?Properties?myProperties?=?new?Properties();

????private?boolean?myIsRunning?=?false;

????private?Thread?myThread?=?null;


????/**?*//**
?????*?Default?constructor.
?????*/
????private?DemoConfigManager()

????
{
????????try

????????
{
????????????String?myConfigFile?=?System.getProperty("RealTimeConfigFile");
????????????if?(myConfigFile?==?null?||?"".equals(myConfigFile))

????????????
{
????????????????myConfigFile?=?"conf/RealTimeConfig.conf";
????????????}
????????????configFile?=?FileResolver.loadFile(myConfigFile);
????????????InputStream?is?=?new?FileInputStream(configFile);
????????????myProperties.load(is);
????????????is.close();
????????}
????????catch?(IOException?ex)

????????
{
????????????System.err.println("Error?reading?RealTimeConfig?configuration?file.?Will?now?exit?RealTimeConfig:?"?+?ex);
????????????System.exit(-1);
????????}
????}


????/**?*//**
?????*?Return?the?name?of?this?subsystem.
?????*/
????public?String?getName()

????
{
????????return?myName;
????}


????/**?*//**
?????*?Get?the?singleton?instance?of?this?class.
?????*?
?????*?@return?The?singleton?instance.
?????*/
????public?static?DemoConfigManager?getInstance()

????
{
????????return?myInstance;
????}


????/**?*//**
?????*?Loads?the?configuration?from?file.
?????*?
?????*?If?find?the?configuration?file?changed,?notify?the?observers
?????*?
?????*?@throws?IOException
?????*?????????????If?unable?to?open?and?read?configuration?file.
?????*/
????private?void?load()?throws?IOException

????
{
????????InputStream?is?=?(InputStream)?new?FileInputStream(configFile);
????????Properties?aFromFileProp?=?new?Properties();
????????aFromFileProp.load(is);

????????//?Check?if?the?properties?in?file?has?been?updated?compared?to?the?stored?properties.
????????if?(!aFromFileProp.toString().equals(myProperties.toString()))

????????
{
????????????myProperties?=?aFromFileProp;
????????????this.setChanged();
????????????this.notifyObservers();
????????}
????????is.close();
????}


????/**?*//**
?????*?The?run?method?of?the?ConfigManager?thread.?It?will?read?the
?????*?configuration?from?file?every?30?seconds.
?????*/
????public?void?run()

????
{
????????while?(myIsRunning)

????????
{
????????????int?interval?=?30;
????????????try

????????????
{
????????????????interval?=?Integer.parseInt(myProperties.getProperty("ReadConfigInterval"));
????????????}
????????????catch?(NumberFormatException?ex)

????????????
{
????????????????myLog.info(
????????????????????????"Error?reading?ReadConfigInterval?config?parameter.?Using?default?value("+interval+").");
????????????}

????????????try

????????????
{
????????????????Thread.sleep(interval?*?1000);
????????????????load();
????????????}
????????????catch?(IOException?ex)

????????????
{
????????????????myLog.info(?"IO?error?while?trying?to?load?config?file:?"
????????????????????????+?ex.getMessage());
????????????}
????????????catch?(InterruptedException?ex)

????????????
{
????????????????
????????????}
????????}
????}


????/**?*//**
?????*?Save?the?configuration?to?file.?Existing?configuration?data?will?be?over
?????*?written.
?????*?
?????*?@throws?IOException
?????*?????????????If?unable?to?open?and?write?to?file.
?????*/
????public?synchronized?void?save()?throws?IOException

????
{
????????OutputStream?os?=?(OutputStream)?new?FileOutputStream(configFile);
????????myProperties.store(os,?"RealTimeConfig");
????????os.close();
????}


????/**?*//**
?????*?Get?a?configuration?value?of?a?specified?parameter?(key).
?????*?
?????*?@param?theKey
?????*????????????The?name?of?the?parameter?to?fetch?a?value?from.
?????*?
?????*?@return?The?configuration?value?for?the?specified?key.
?????*/
????public?synchronized?String?get(String?theKey)

????
{
????????return?myProperties.getProperty(theKey);
????}


????/**?*//**
?????*?Set?a?configuration?value?of?a?specified?parameter?(key).
?????*?
?????*?@param?theKey
?????*????????????The?name?of?the?parameter?to?set.
?????*?
?????*?@param?theValue
?????*????????????The?value?of?the?parameter?to?set.
?????*/
????public?synchronized?void?set(String?theKey,?String?theValue)

????
{
????????myProperties.setProperty(theKey,?theValue);
????}


????/**?*//**
?????*?Get?all?parameters?contained?in?the?ConfigManager.
?????*?
?????*?@return?A?Properties?object?containing?all?configuration?parameters?and
?????*?????????their?value.
?????*/
????public?synchronized?Properties?getProperties()

????
{
????????return?myProperties;
????}


????/**?*//**
?????*?Start?the?ConfigManager?and?read?configuration?from?file.?From?now?on?the
?????*?configuration?will?be?read?from?file?at?a?configurable?interval,?default
?????*?30?seconds.
?????*/
????public?synchronized?void?startup()?throws?StartupFailureException

????
{
????????if?(myIsRunning)

????????
{
????????????throw?new?StartupFailureException("Subsystem?is?already?running!");
????????}

????????myIsRunning?=?true;

????????myThread?=?new?Thread(this,?this.getName());
????????myThread.start();
????}


????/**?*//**
?????*?Shuts?down?the?ConfigManager.
?????*?
?????*?@param?theGracefulShutdownMode
?????*????????????<code>true</code>?if?shut?down?should?be?graceful,
?????*????????????<code>false</code>?otherwise.
?????*/
????public?synchronized?void?shutdown(boolean?theGracefulShutdownMode)
????????????throws?ShutdownFailureException

????
{
????????if?(!this.isRunning())

????????
{
????????????throw?new?ShutdownFailureException("Subsystem?is?already?stopped!");
????????}

????????myIsRunning?=?false;
????????try

????????
{
????????????myThread.interrupt();
????????????myThread.join(1?*?60?*?1000);
????????}
????????catch?(InterruptedException?ex)

????????
{
????????}
????????catch?(SecurityException?ex)

????????
{
????????}

????????myThread?=?null;
????}


????/**?*//**
?????*?Checks?if?the?ConfigManager?is?alive.
?????*?
?????*?@return?<code>true</code>?if?alive,?otherwise?<code>false</code>.
?????*/
????public?boolean?isRunning()

????
{
????????return?(myThread?!=?null?&&?myThread.isAlive()?&&?myIsRunning);
????}
}

posted on 2008-09-04 14:49
jht 閱讀(1321)
評論(0) 編輯 收藏 所屬分類:
J2SE