package com.xiaoleilu.hutool.setting.dialect; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URL; import java.nio.file.Paths; import java.nio.file.WatchEvent; import java.util.Properties; import com.xiaoleilu.hutool.convert.Convert; import com.xiaoleilu.hutool.getter.BasicTypeGetter; import com.xiaoleilu.hutool.getter.OptBasicTypeGetter; import com.xiaoleilu.hutool.io.FileUtil; import com.xiaoleilu.hutool.io.IoUtil; import com.xiaoleilu.hutool.io.resource.ClassPathResource; import com.xiaoleilu.hutool.io.resource.UrlResource; import com.xiaoleilu.hutool.io.watch.SimpleWatcher; import com.xiaoleilu.hutool.io.watch.WatchMonitor; import com.xiaoleilu.hutool.lang.Assert; import com.xiaoleilu.hutool.log.Log; import com.xiaoleilu.hutool.log.StaticLog; import com.xiaoleilu.hutool.setting.SettingRuntimeException; import com.xiaoleilu.hutool.util.CollectionUtil; import com.xiaoleilu.hutool.util.StrUtil; /** * Properties文件读取封装类 * @author loolly */ public final class Props extends Properties implements BasicTypeGetter<String>, OptBasicTypeGetter<String>{ private static final long serialVersionUID = 1935981579709590740L; private final static Log log = StaticLog.get(); //----------------------------------------------------------------------- 私有属性 start /** 属性文件的URL */ private URL propertiesFileUrl; private WatchMonitor watchMonitor; //----------------------------------------------------------------------- 私有属性 end /** * 获得Classpath下的Properties文件 * * @param resource 资源(相对Classpath的路径) * @return Properties */ public static Properties getProp(String resource) { return new Props(resource); } //----------------------------------------------------------------------- 构造方法 start /** * 构造 */ public Props() { super(); } /** * 构造,使用相对于Class文件根目录的相对路径 * @param pathBaseClassLoader 相对路径(相对于当前项目的classes路径) */ public Props(String pathBaseClassLoader){ Assert.notBlank(pathBaseClassLoader, "Blank properties file path !"); this.load(new ClassPathResource(pathBaseClassLoader)); } /** * 构造 * @param propertiesFile 配置文件对象 */ public Props(File propertiesFile){ Assert.notNull(propertiesFile, "Null properties file!"); this.load(new UrlResource(propertiesFile)); } /** * 构造,相对于classes读取文件 * @param path 相对路径 * @param clazz 基准类 */ public Props(String path, Class<?> clazz){ Assert.notBlank(path, "Blank properties file path !"); this.load(new ClassPathResource(path, clazz)); } /** * 构造,使用URL读取 * @param propertiesUrl 属性文件路径 */ public Props(URL propertiesUrl){ Assert.notNull(propertiesUrl, "Null properties URL !"); this.load(new UrlResource(propertiesUrl)); } /** * 构造,使用URL读取 * @param properties 属性文件路径 */ public Props(Properties properties){ if(CollectionUtil.isNotEmpty(properties)){ this.putAll(properties); } } //----------------------------------------------------------------------- 构造方法 end /** * 初始化配置文件 * @param urlResource {@link UrlResource} */ public void load(UrlResource urlResource){ this.propertiesFileUrl = urlResource.getUrl(); if(null == this.propertiesFileUrl) { throw new SettingRuntimeException("Can not find properties file: [{}]", urlResource); } log.debug("Load properties [{}]", propertiesFileUrl.getPath()); InputStream in = null; try { in = urlResource.getStream(); super.load(in); } catch (Exception e) { log.error(e, "Load properties error!"); }finally{ IoUtil.close(in); } } /** * 重新加载配置文件 */ public void load() { this.load(new UrlResource(this.propertiesFileUrl)); } /** * 在配置文件变更时自动加载 * @param autoReload 是否自动加载 */ public void autoLoad(boolean autoReload){ if(autoReload){ if(null != this.watchMonitor){ this.watchMonitor.close(); try { watchMonitor = WatchMonitor.create(Paths.get(this.propertiesFileUrl.toURI())); watchMonitor.setWatcher(new SimpleWatcher(){ @Override public void onModify(WatchEvent<?> event) { load(); } }).start(); } catch (Exception e) { throw new SettingRuntimeException(e, "Setting auto load not support url: [{}]", this.propertiesFileUrl); } } }else{ IoUtil.close(this.watchMonitor); this.watchMonitor = null; } } //----------------------------------------------------------------------- Get start @Override public Object getObj(String key, Object defaultValue) { return getStr(key, null == defaultValue ? null : defaultValue.toString()); } @Override public Object getObj(String key) { return getObj(key, null); } @Override public String getStr(String key, String defaultValue){ return super.getProperty(key, defaultValue); } @Override public String getStr(String key){ return super.getProperty(key); } @Override public Integer getInt(String key, Integer defaultValue){ return Convert.toInt(getStr(key), defaultValue); } @Override public Integer getInt(String key){ return getInt(key, null); } @Override public Boolean getBool(String key, Boolean defaultValue){ return Convert.toBool(getStr(key), defaultValue); } @Override public Boolean getBool(String key){ return getBool(key, null); } @Override public Long getLong(String key, Long defaultValue){ return Convert.toLong(getStr(key), defaultValue); } @Override public Long getLong(String key){ return getLong(key, null); } @Override public Character getChar(String key, Character defaultValue) { final String value = getStr(key); if(StrUtil.isBlank(value)) { return defaultValue; } return value.charAt(0); } @Override public Character getChar(String key) { return getChar(key, null); } @Override public Float getFloat(String key) { return getFloat(key, null); } @Override public Float getFloat(String key, Float defaultValue) { return Convert.toFloat(getStr(key), defaultValue); } @Override public Double getDouble(String key, Double defaultValue) throws NumberFormatException { return Convert.toDouble(getStr(key), defaultValue); } @Override public Double getDouble(String key) throws NumberFormatException { return getDouble(key, null); } @Override public Short getShort(String key, Short defaultValue) { return Convert.toShort(getStr(key), defaultValue); } @Override public Short getShort(String key) { return getShort(key, null); } @Override public Byte getByte(String key, Byte defaultValue) { return Convert.toByte(getStr(key), defaultValue); } @Override public Byte getByte(String key) { return getByte(key, null); } @Override public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) { final String valueStr = getStr(key); if(StrUtil.isBlank(valueStr)) { return defaultValue; } try { return new BigDecimal(valueStr); } catch (Exception e) { return defaultValue; } } @Override public BigDecimal getBigDecimal(String key) { return getBigDecimal(key, null); } @Override public BigInteger getBigInteger(String key, BigInteger defaultValue) { final String valueStr = getStr(key); if(StrUtil.isBlank(valueStr)) { return defaultValue; } try { return new BigInteger(valueStr); } catch (Exception e) { return defaultValue; } } @Override public BigInteger getBigInteger(String key) { return getBigInteger(key, null); } @Override public <E extends Enum<E>> E getEnum(Class<E> clazz, String key, E defaultValue) { return Convert.toEnum(clazz, getStr(key), defaultValue); } @Override public <E extends Enum<E>> E getEnum(Class<E> clazz, String key) { return getEnum(clazz, key, null); } //----------------------------------------------------------------------- Get end //----------------------------------------------------------------------- Set start /** * 设置值,无给定键创建之。设置后未持久化 * @param key 属性键 * @param value 属性值 */ public void setProperty(String key, Object value){ super.setProperty(key, value.toString()); } /** * 持久化当前设置,会覆盖掉之前的设置 * @param absolutePath 设置文件的绝对路径 */ public void store(String absolutePath){ try { FileUtil.touch(absolutePath); super.store(FileUtil.getOutputStream(absolutePath), null); } catch (FileNotFoundException e) { //不会出现这个异常 } catch (IOException e) { log.error(e, "Store properties to [{}] error!", absolutePath); } } /** * 存储当前设置,会覆盖掉以前的设置 * @param path 相对路径 * @param clazz 相对的类 */ public void store(String path, Class<?> clazz){ this.store(FileUtil.getAbsolutePath(path, clazz)); } //----------------------------------------------------------------------- Set end }