• 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=default
    string.in.defaultAndUserdefine=default
    string.in.all=default

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

    string.in.defaultAndUserdefine=userdefine
    string.in.all=userdefine
    
    int.positive=1000
    int.negative=-1000
    int.overflow=2147483648
    int.underflow=-2147483649
    
    boolean.true=TruE
    boolean.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

    源码下载Github https://github.com/Mov-hh/java-demo

  • 相关阅读:
    form表单有条件的提交
    当月第一天、最后一天、下月第一天,时间date
    网站分享
    如何做浏览器网站搜索
    js关闭当前页面跳转新页面
    img图片居中
    laravel 重定向路由带参数
    线段判严格相交+思维——poj1066
    线段判非严格相交+暴力——poj2653
    线段判严格相交+最短路建图——poj1556
  • 原文地址:https://www.cnblogs.com/xxt-mov/p/4243226.html
Copyright © 2020-2023  润新知