当前位置: 代码迷 >> Java相关 >> properties属性文件设计&实践(一)
  详细解决方案

properties属性文件设计&实践(一)

热度:456   发布时间:2016-04-22 20:46:10.0
properties属性文件设计&实践(1)

在项目中,一般会在类路径下存在这样的一个属性文件,如:config.properties systemconfig.properties等,通过属性文件可以实现以下目的
1. 统一维护公用的配置性属性
2. 不修改class/jar,改变类的行为

一般还会针对此属性文件提供一个类来读取其属性

 

本文介绍一种在设计公用代码时的属性文件通用设计思路,即多个属性文件
1. 默认属性文件
    在公用代码工程维护,发布时直接打包到jar中,其中的属性会被2、3覆盖
2. 各工程自定义属性文件
    在公用代码工程不维护,使用者提供,其中属性会被3覆盖
3. 不可覆盖的属性文件
    公用代码工程维护,发布时直接打包到jar中

 

具体实现

1.Configuration 属性读取类

2.config.default.properties 默认属性文件

3.config.properties 各工程自定义属性文件

4.config.nooverride.properties 不可覆盖的属性文件

 

1.Configuration 属性读取类

 

package mov.demo;import java.io.IOException;import java.io.InputStream;import java.util.Properties;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * 属性读取类 * @author mov * @since 0.0.1 */public class Configuration {    private static Logger log = LoggerFactory.getLogger(Configuration.class);        private static Properties props = new Properties();;        /** 默认属性文件 */    private static final String CONFIG_FILE_DEFAULT = "config.default.properties";        /** 各工程自定义配置 */    private static final String CONFIG_FILE_USER_DEFINED = "config.properties";        /** 不可覆盖的属性文件 */    private static final String CONFIG_FILE_NO_OVERRIDE = "config.nooverride.properties";    static {        int successLoadedCount = 0;        /* 先加载默认配置 */        if (loadConfig(CONFIG_FILE_DEFAULT)) {            ++successLoadedCount;        }                /* 再加载用户自定义配置,以覆盖默认 */        if (loadConfig(CONFIG_FILE_USER_DEFINED)) {            ++successLoadedCount;        }        /* 最后加载不可覆盖的配置,以覆盖所有 */        if (loadConfig(CONFIG_FILE_NO_OVERRIDE)) {            ++successLoadedCount;        }                if (successLoadedCount == 0) {            log.error("all config file load error");        }    }    /**     * 获取属性值     * @param key     * @return 属性存在时返回对应的值,否则返回""     */     public static String getCfgValue(String key) {        return getCfgValue(key, "");    }        /**     * 获取属性值     * @param key     * @param defaultValue     * @return 属性存在时返回对应的值,否则返回defaultValue     */     public static String getCfgValue(String key, String defaultValue) {        return props.getProperty(key, defaultValue);    }        /**     * 获取属性值     * @param key     * @return 属性存在且可以转为int时返回对应的值,否则返回0     */    public static int getIntCfgValue(String key) {        return getIntCfgValue(key, 0);    }    /**     * 获取属性值     * @param key     * @param defaultValue     * @return 属性存在且可以转为int时时返回对应的值,否则返回defaultValue     */    public static int getIntCfgValue(String key, int defaultValue) {        String val = getCfgValue(key);        if (!isEmpty(val)) {            try {                return Integer.parseInt(val);            } catch (NumberFormatException e) {                log.warn("error get config. value '{}' is not a valid int for key '{}'"                        , val, key);            }        }                return defaultValue;    }        /**     * 获取属性值     * @param key     * @return 属性存在时返回对应的值,否则返回false     */    public static boolean getBooleanCfgValue(String key) {        return getBooleanCfgValue(key, false);    }        /**     * 获取属性值     * @param key     * @param defaultValue     * @return 属性存在时返回对应的值,否则返回defaultValue     */    public static boolean getBooleanCfgValue(String key, boolean defaultValue) {        String val = getCfgValue(key);        if (!isEmpty(val)) {            return Boolean.parseBoolean(val);        } else {            return defaultValue;        }    }    private static boolean loadConfig(String configFile) {        boolean success = false;        InputStream inputStream = null;        try {            inputStream = Configuration.class.getClassLoader().getResourceAsStream(configFile);                        if (inputStream != null) {                props.load(inputStream);                success = true;            } else {                log.warn("project config file 'classpath:{}' not found", configFile);            }        } catch (Throwable e) {            log.error("error load config file 'classpath:{}'", configFile, e);        } finally {            if (inputStream != null) {                try {                    inputStream.close();                } catch (IOException e) {                    // do nothing                }            }        }                return success;    }        private static boolean isEmpty(String val) {        return val == null || val.length() == 0;    }}

 

2.config.default.properties 默认属性文件

string.in.default=defaultstring.in.defaultAndUserdefine=defaultstring.in.all=default

 

3.config.properties 各工程自定义属性文件

string.in.defaultAndUserdefine=userdefinestring.in.all=userdefineint.positive=1000int.negative=-1000int.overflow=2147483648int.underflow=-2147483649boolean.true=TruEboolean.false=whatever

 

4.config.nooverride.properties 不可覆盖的属性文件

string.in.all=nooverride

 

单元测试

package mov.demo;import static org.junit.Assert.*;import org.junit.Test;public class ConfigurationTest {    @Test    public void testGetCfgValueString() {        assertEquals("", Configuration.getCfgValue("not.exists"));        assertEquals("default", Configuration.getCfgValue("string.in.default"));        assertEquals("userdefine", Configuration.getCfgValue("string.in.defaultAndUserdefine"));        assertEquals("nooverride", Configuration.getCfgValue("string.in.all"));    }    @Test    public void testGetCfgValueStringString() {        assertEquals(null, Configuration.getCfgValue("not.exists", null));        assertEquals("default", Configuration.getCfgValue("string.in.default", null));        assertEquals("userdefine", Configuration.getCfgValue("string.in.defaultAndUserdefine", null));        assertEquals("nooverride", Configuration.getCfgValue("string.in.all", null));    }    @Test    public void testGetIntCfgValueString() {        assertEquals(0, Configuration.getIntCfgValue("not.exists"));        assertEquals(1000, Configuration.getIntCfgValue("int.positive"));        assertEquals(-1000, Configuration.getIntCfgValue("int.negative"));        assertEquals(0, Configuration.getIntCfgValue("int.overflow"));        assertEquals(0, Configuration.getIntCfgValue("int.underflow"));    }    @Test    public void testGetIntCfgValueStringInt() {        assertEquals(-1, Configuration.getIntCfgValue("not.exists", -1));        assertEquals(1000, Configuration.getIntCfgValue("int.positive", -1));        assertEquals(-1000, Configuration.getIntCfgValue("int.negative", -1));        assertEquals(-1, Configuration.getIntCfgValue("int.overflow", -1));        assertEquals(-1, Configuration.getIntCfgValue("int.underflow", -1));    }    @Test    public void testGetBooleanCfgValueString() {        assertFalse(Configuration.getBooleanCfgValue("not.exists"));        assertTrue(Configuration.getBooleanCfgValue("boolean.true"));        assertFalse(Configuration.getBooleanCfgValue("boolean.false"));    }    @Test    public void testGetBooleanCfgValueStringBoolean() {        assertTrue(Configuration.getBooleanCfgValue("not.exists", true));        assertTrue(Configuration.getBooleanCfgValue("boolean.true", false));        assertFalse(Configuration.getBooleanCfgValue("boolean.false", true));    }}

 

运行单元测试类,结果如下

image

  相关解决方案