Dynamically loading properties file using Spring

我们两清 提交于 2019-11-30 05:52:55

问题


I have written a PropertyUtils class (from internet), which will load the Properties

<bean id="propertiesUtil" class="com.myApp.PropertiesUtil" >
    <property name="locations">
        <list>
            <value>classpath:myApp/myApp.properties</value>         
        </list>
    </property>
</bean>

and a PropertiesUtil class is like below

public class PropertiesUtil extends PropertyPlaceholderConfigurer {

    private static Map<String, String> properties = new HashMap<String, String>();

    @Override
    protected void loadProperties(final Properties props) throws IOException {
        super.loadProperties(props);
        for (final Object key : props.keySet()) {
            properties.put((String) key, props.getProperty((String) key));
        }
    }

    public String getProperty(final String name) {
        return properties.get(name);
    }

}

Later, I can get the property by calling PropertiesUtil.getProperty() method.

But now I want to modify it slightly such that, If the myApp.properties get modified/changed by user, it should be loaded again

Probably I need FileWatcher class

public abstract class FileWatcher extends TimerTask {
    private long timeStamp;
    private File file;

    public FileWatcher(File file) {
        this.file = file;
        this.timeStamp = file.lastModified();
    }

    @Override
    public final void run() {
        long timeStampNew = this.file.lastModified();

        if (this.timeStamp != timeStampNew) {
            this.timeStamp = timeStampNew;
            onChange(this.file);
        }
    }

    protected abstract void onChange(File newFile);
}

but my doubts are

  1. How do I create File object using classpath:myApp/myApp.properties (because absolute path is not known)
  2. How do I invoke/call spring to load/pass the new myApp.properties to PropetisUtil class [in onChange method].

回答1:


You can use Spring's ReloadableResourceBundleMessageSource class like below:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <bean id="myProperties" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <!-- check property file(s) every 1 second -->
        <property name="cacheSeconds" value="1"/>
        <property name="basenames">
            <list>
                <value>myApp/myApp</value>
            </list>
        </property>
    </bean>

</beans>

And then you can call MessageSource.getMessage() method to get the property value. Here is an example:

package com.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.MessageSource;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyApp {
public static void main(String[] args) throws InterruptedException {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("myApp/MyApp.xml");
        MessageSource myProperties = (MessageSource) ctx.getBean("myProperties");
        while (true) {
            System.out.println(myProperties.getMessage("myApp.propertyOne", null, null));
            Thread.sleep(1000);
        }
    }
} 

You can directly call ApplicationContext.getMessage(String code, Object[] args, Locale locale) if you renamed your 'myProperties' bean as 'messageSource'.

For your web apps, please put your property files outside of your web app's classpath (because the web server might cache them). For instance, WEB-INF/conf/myApp.properties




回答2:


The following supports what you are looking for:

https://commons.apache.org/proper/commons-configuration/userguide/howto_properties.html

PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties");
config.setReloadingStrategy(new FileChangedReloadingStrategy());

This should do the trick. I haven't used it myself but it seems to be pretty straightforward.




回答3:


May be the simpler way would be to do like this:

<util:properties location="classpath:config.properties" id="configProperties" />
<context:property-placeholder properties-ref="configProperties"  />

This way you can access your properties from any bean by injecting/accessing bean with a name "configProperties". Not sure if this is what you need, because it is not possible to modify configProperties at runtime. But this is a clean way and you do not need to write any additional class.



来源:https://stackoverflow.com/questions/14117117/dynamically-loading-properties-file-using-spring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!