001package net.gdface.utils; 002 003import java.io.File; 004import java.io.FileWriter; 005import java.io.IOException; 006import java.io.InputStream; 007import java.io.InputStreamReader; 008import java.net.URL; 009import java.util.HashSet; 010import java.util.Properties; 011import java.util.Set; 012 013/** 014 * 配置文件读取工具类 015 * @author guyadong 016 * 017 */ 018public class ConfigUtils { 019 private static final String JAR_SUFFIX = ".jar"; 020 021 /** 022 * 顺序加载不同位置的properties文件,加载顺序为:<br> 023 * 1.调用{@link ClassLoader#getResource(String)}方法在{@code clazz}所在位置查找,如果失败则抛出异常<br> 024 * 2.如果class在jar包中,则尝试读取在jar所在位置../confFolder/propFile,tomcat下即为WEB-INF/confFolder/propFile<br> 025 * 3.如果环境变量envVar定义,则从envVar指定的目录下读取propFile<br> 026 * 4.user.dir下查找confFolder/propFile加载配置<br> 027 * 后面的配置变量会覆盖前面的定义<br> 028 * @param propFile 要加载的properties文件名,为{@code null}或空时抛出异常 {@link IllegalArgumentException} 029 * @param confFolder popFile所在文件夹,{@code null}时使用默认值'conf' 030 * @param envVar 环境变量名 用于定义propFile位置,可为{@code null} 031 * @param clazz 用于获取 {@link ClassLoader}的类,为null时使用本类的class 032 * @param showProp 加载后是否显示所有值 033 * @return 返回加载后的{@link Properties}对象 034 */ 035 public static Properties loadAllProperties(String propFile, String confFolder, String envVar, Class<?> clazz, boolean showProp) { 036 if(null==propFile||propFile.isEmpty()){ 037 throw new IllegalArgumentException("the argument 'propFile' must not be null or empty"); 038 } 039 if (null == confFolder){ 040 confFolder = "conf"; 041 } 042 if (null == clazz){ 043 clazz = ConfigUtils.class; 044 } 045 final String fileSeparator = System.getProperty("file.separator"); 046 String propPath = confFolder.concat(System.getProperty("file.separator")).concat(propFile); 047 Properties props = new Properties(); 048 Set<File> loadedFiles = new HashSet<File>(); 049 try { 050 // 在jar包中查找默认配置文件 051 URL url = clazz.getClassLoader().getResource(propPath.replace(fileSeparator, "/")); 052 if(null==url){ 053 throw new ExceptionInInitializerError(String.format("not found default properties %s", propPath)); 054 } 055 loadProperties(url, props); 056 } catch (Exception e) { 057 // 默认配置必须加载成功否则抛出异常 058 throw new ExceptionInInitializerError(String.format("fail to load default properties(加载默认配置文件失败) %s cause by %s", propPath, 059 e.getMessage())); 060 } 061 try { 062 // 加载 jar包所在位置 ../conf/cassdk.properties 063 URL classLocation = clazz.getProtectionDomain().getCodeSource().getLocation(); 064 if (classLocation.toString().endsWith(JAR_SUFFIX)) { 065 // jar包所在目录的父目录,tomcat下即为WEB-INF 066 File jarParent = new File(classLocation.getPath()).getParentFile().getParentFile(); 067 if (null != jarParent) { 068 File confFile = new File(jarParent, propPath); 069 if (confFile.isFile()) { 070 loadProperties(confFile.toURI().toURL(), props); 071 loadedFiles.add(confFile); 072 } 073 } 074 } 075 } catch (Exception e) { 076 } 077 try { 078 // 通过环境变量查找properties文件 079 if (envVar != null && !envVar.isEmpty()) { 080 String cf = System.getProperty(envVar); 081 if (null != cf&&!cf.isEmpty()) { 082 File envFile = new File(cf, propFile); 083 if (!loadedFiles.contains(envFile)) { 084 loadProperties(envFile.toURI().toURL(), props); 085 loadedFiles.add(envFile); 086 } 087 } else{ 088 log("not defined environment variable '%s'", envVar); 089 } 090 } 091 } catch (Exception e) { 092 } 093 try { 094 // 在当前路径下查找配置文件 095 File propInUserDir = new File(System.getProperty("user.dir"), propPath); 096 if (propInUserDir.isFile() && !loadedFiles.contains(propInUserDir)) { 097 loadProperties(propInUserDir.toURI().toURL(), props); 098 loadedFiles.add(propInUserDir); 099 } 100 } catch (Exception e) { 101 } 102 103 // 输出所有参数值 104 if(showProp){ 105 props.list(System.out); 106 } 107 return props; 108 } 109 110 /** 111 * 基于user.home,加载相对路径propPath指定的properties文件 112 * @param propPath 113 * @return 114 */ 115 public static Properties loadPropertiesInUserHome(String propPath){ 116 Properties props = new Properties(); 117 try { 118 // 在user.home路径下查找配置文件 119 File propInUserHome = new File(System.getProperty("user.home"), propPath); 120 if (propInUserHome.isFile() ) { 121 loadProperties(propInUserHome.toURI().toURL(), props); 122 } 123 } catch (Exception e) { 124 } 125 return props; 126 } 127 /** 128 * 基于user.home,保存指定的{@link Properties} 129 * @param properties 130 * @param propertiesFile properties文件名 131 * @throws IOException 132 * @see {@link Properties#store(java.io.Writer, String)} 133 * @see {@link System#getProperties()} 134 */ 135 public static void storePropertiesInUserHome(Properties properties,String propertiesFile) throws IOException{ 136 if(null==properties){ 137 throw new NullPointerException(); 138 } 139 if(null==propertiesFile||propertiesFile.isEmpty()){ 140 throw new IllegalArgumentException("propertiesFile must not be empty or null"); 141 } 142 File propInUserHome = new File(System.getProperty("user.home"), propertiesFile); 143 File parent=propInUserHome.getParentFile(); 144 if(!parent.exists()){ 145 parent.mkdirs(); 146 } 147 properties.store(new FileWriter(propInUserHome), null); 148 149 } 150 /** 151 * configure with the parameters given in the given url 152 * 153 * @param url 154 * the resource filename to be used 155 * @param props 156 * dest properties to add 157 * @throws IOException 158 */ 159 private static void loadProperties(URL url, Properties props) throws IOException { 160 if (null != url) { 161 InputStream is = null; 162 try { 163 props.load(new InputStreamReader(is = url.openStream(),"UTF-8")); 164 log("Load properties from %s", url.toString()); 165 } finally { 166 if (is != null){ 167 is.close(); 168 } 169 } 170 } 171 } 172 private static void log(String format, Object ... args){ 173 System.out.printf("[%s:%d]%s\n", 174 ConfigUtils.class.getSimpleName(), 175 Thread.currentThread() .getStackTrace()[2].getLineNumber(), 176 String.format(format, args)); 177 } 178}