自動搜尋不同位置的properties檔案並載入
阿新 • • 發佈:2019-02-16
在專案開發中,對於一些程式執行的引數可能經常需要根據實際情況修改或調整,所以這些引數我們不會在程式碼中寫死,而是它們儲存在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