自动搜索不同位置的properties文件并加载

在项目开发中,对于一些程序运行的参数可能经常需要根据实际情况修改或调整,所以这些参数我们不会在代码中写死,而是它们保存在properties(或xml)文件中,以方便修改。这时就需要智能加载要配置文件,如何智能加载,我想要的加载顺序:

1. jar包所在目录(加载jar包里的初始值)
2. 项目所在目录(调用jar的程序)
3. 用户工作目录(use.dir)

下面是完整的java代码:

package net.gdface.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

public class ConfigUtils {
    /**
     * 顺序加载不同位置的properties文件,加载顺序为:<br>
     * 1.调用{@link ClassLoader#getResource(String)}方法在{@code clazz}所在位置查找,如果失败则抛出异常<br>
     * 2.如果class在jar包中,则尝试读取在jar所在位置../confFolder/propFile,tomcat下即为WEB-INF/confFolder/propFile<br>
     * 3.如果环境变量envVar定义,则从envVar指定的目录下读取propFile<br>
     * 4.user.dir下查找confFolder/propFile加载配置<br>
     * 后面的配置变量会覆盖前面的定义<br>
     * @param propFile 要加载的properties文件名,为{@code null}或空时抛出异常 {@link IllegalArgumentException}
     * @param confFolder popFile所在文件夹,{@code null}时使用默认值'conf'
     * @param envVar 环境变量名 用于定义propFile位置,可为{@code null}
     * @param clazz 用于获取 {@link ClassLoader}的类,为null时使用本类的class
     * @param showProp 加载后是否显示所有值
     * @return 返回加载后的{@link Properties}对象
     */
    public static Properties loadAllProperties(String propFile, String confFolder, String envVar, Class<?> clazz, boolean showProp) {
        if(null==propFile||propFile.isEmpty())
            throw new IllegalArgumentException("the argument 'propFile' must not be null or empty");
        if (null == confFolder)
            confFolder = "conf";
        if (null == clazz)
            clazz = ConfigUtils.class;
        final String fileSeparator = System.getProperty("file.separator");
        String prop_path = confFolder.concat(System.getProperty("file.separator")).concat(propFile);
        Properties props = new Properties();
        Set<File> loaded_files = new HashSet<File>();
        try {
            // 在jar包中查找默认配置文件
            URL url = clazz.getClassLoader().getResource(prop_path.replace(fileSeparator, "/"));
            if(null==url)
                throw new ExceptionInInitializerError(String.format("not found default properties %s", prop_path));
            loadProperties(url, props);
        } catch (Exception e) {
            // 默认配置必须加载成功否则抛出异常
            throw new ExceptionInInitializerError(String.format("fail to load default properties(加载默认配置文件失败) %s cause by %s", prop_path,
                    e.getMessage()));
        }
        try {
            // 加载 jar包所在位置 ../conf/cassdk.properties
            URL class_location = clazz.getProtectionDomain().getCodeSource().getLocation();
            if (class_location.toString().endsWith(".jar")) {
                // jar包所在目录的父目录,tomcat下即为WEB-INF
                File jar_parent = new File(class_location.getPath()).getParentFile().getParentFile();
                if (null != jar_parent) {
                    File conf_file = new File(jar_parent, prop_path);
                    if (conf_file.isFile()) {
                        loadProperties(conf_file.toURI().toURL(), props);
                        loaded_files.add(conf_file);
                    }
                }
            }
        } catch (Exception e) {
        }
        try {
            // 通过环境变量查找properties文件
            if (envVar != null && !envVar.isEmpty()) {
                String cf = System.getProperty(envVar);
                if (null != cf&&!cf.isEmpty()) {
                    File env_file = new File(cf, propFile);
                    if (!loaded_files.contains(env_file)) {
                        loadProperties(env_file.toURI().toURL(), props);
                        loaded_files.add(env_file);
                    }
                } else
                    log("not defined environment variable '%s'", envVar);
            }
        } catch (Exception e) {
        }
        try {
            // 在当前路径下查找配置文件
            File propInUserDir = new File(System.getProperty("user.dir"), prop_path);
            if (propInUserDir.isFile() && !loaded_files.contains(propInUserDir)) {
                loadProperties(propInUserDir.toURI().toURL(), props);
                loaded_files.add(propInUserDir);
            }
        } catch (Exception e) {
        }

        // 输出所有参数值
        if(showProp)
            props.list(System.out);
        return props;
    }

    /**
     * configure with the parameters given in the given url
     * 
     * @param url
     *            the resource filename to be used
     * @param props
     *            dest properties to add
     * @throws IOException
     */
    private static void loadProperties(URL url, Properties props) throws IOException {
        if (null != url) {
            InputStream is = null;
            try {
                props.load(is = url.openStream());
                log("Load properties from %s", url.toString());
            } finally {
                if (is != null)
                    is.close();
            }           
        }
    }
    /*
     * 这个类原本是用sl4j做日志输出的,因为这里需要输出的日志比较少,<br>
     * 而且为了增强该类的独立性减少对第三方jar包的依赖,<br>
     * 在此改为一个简单的log方法来输出信息,输出信息中会包含类名和行号 
     */
    private static void log(String format, Object ... args){
        System.out.printf("[%s:%d]%s\n", 
                ConfigUtils.class.getSimpleName(),
                Thread.currentThread() .getStackTrace()[2].getLineNumber(),
                String.format(format, args));
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128

如果上面三个目录里文件存在相同的key,后面加载将覆盖前面的ps: this.class.getProtectionDomain().getCodeSource().getLocation()

如果直接执行.class文件那么会得到当前class的绝对路径:

file:/E:/melt/workspace/bpmsAnalysis/build/classes/

如果封装在jar包里面执行jar包那么会得到当前jar包的绝对路径:

file:/E:/melt/workspace/bpmsAnalysis/WebContent/WEB-INF/lib/JdbcUtils.jar

通过执行目录来决定把文件放src下,还是要WEB-INF下


转:http://blog.csdn.net/10km/article/details/52100365



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值