All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hutool.setting.dialect.Props Maven / Gradle / Ivy

There is a newer version: 5.8.33
Show newest version
package cn.hutool.setting.dialect;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.getter.BasicTypeGetter;
import cn.hutool.core.getter.OptBasicTypeGetter;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.io.resource.FileResource;
import cn.hutool.core.io.resource.Resource;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.io.resource.UrlResource;
import cn.hutool.core.io.watch.SimpleWatcher;
import cn.hutool.core.io.watch.WatchMonitor;
import cn.hutool.core.io.watch.WatchUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.StaticLog;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.util.Date;
import java.util.Properties;

/**
 * Properties文件读取封装类
 *
 * @author loolly
 */
public final class Props extends Properties implements BasicTypeGetter, OptBasicTypeGetter {
	private static final long serialVersionUID = 1935981579709590740L;

	/**
	 * 默认配置文件扩展名
	 */
	public final static String EXT_NAME = "properties";

	/**
	 * 构建一个空的Props,用于手动加入参数
	 *
	 * @return Setting
	 * @since 5.4.3
	 */
	public static Props create() {
		return new Props();
	}

	// ----------------------------------------------------------------------- 私有属性 start
	/**
	 * 属性文件的Resource
	 */
	private Resource resource;
	private WatchMonitor watchMonitor;
	/**
	 * properties文件编码
* issue#1701,此属性不能被序列化,故忽略序列化 */ private transient Charset charset = CharsetUtil.CHARSET_ISO_8859_1; // ----------------------------------------------------------------------- 私有属性 end /** * 获得Classpath下的Properties文件 * * @param resource 资源(相对Classpath的路径) * @return Props */ public static Props getProp(String resource) { return new Props(resource); } /** * 获得Classpath下的Properties文件 * * @param resource 资源(相对Classpath的路径) * @param charsetName 字符集 * @return Properties */ public static Props getProp(String resource, String charsetName) { return new Props(resource, charsetName); } /** * 获得Classpath下的Properties文件 * * @param resource 资源(相对Classpath的路径) * @param charset 字符集 * @return Properties */ public static Props getProp(String resource, Charset charset) { return new Props(resource, charset); } // ----------------------------------------------------------------------- 构造方法 start /** * 构造 */ public Props() { } /** * 构造,使用相对于Class文件根目录的相对路径 * * @param path 配置文件路径,相对于ClassPath,或者使用绝对路径 */ public Props(String path) { this(path, CharsetUtil.CHARSET_ISO_8859_1); } /** * 构造,使用相对于Class文件根目录的相对路径 * * @param path 相对或绝对路径 * @param charsetName 字符集 */ public Props(String path, String charsetName) { this(path, CharsetUtil.charset(charsetName)); } /** * 构造,使用相对于Class文件根目录的相对路径 * * @param path 相对或绝对路径 * @param charset 字符集 */ public Props(String path, Charset charset) { Assert.notBlank(path, "Blank properties file path !"); if (null != charset) { this.charset = charset; } this.load(ResourceUtil.getResourceObj(path)); } /** * 构造 * * @param propertiesFile 配置文件对象 */ public Props(File propertiesFile) { this(propertiesFile, StandardCharsets.ISO_8859_1); } /** * 构造 * * @param propertiesFile 配置文件对象 * @param charsetName 字符集 */ public Props(File propertiesFile, String charsetName) { this(propertiesFile, Charset.forName(charsetName)); } /** * 构造 * * @param propertiesFile 配置文件对象 * @param charset 字符集 */ public Props(File propertiesFile, Charset charset) { Assert.notNull(propertiesFile, "Null properties file!"); this.charset = charset; this.load(new FileResource(propertiesFile)); } /** * 构造,相对于classes读取文件 * * @param path 相对路径 * @param clazz 基准类 */ public Props(String path, Class clazz) { this(path, clazz, CharsetUtil.ISO_8859_1); } /** * 构造,相对于classes读取文件 * * @param path 相对路径 * @param clazz 基准类 * @param charsetName 字符集 */ public Props(String path, Class clazz, String charsetName) { this(path, clazz, CharsetUtil.charset(charsetName)); } /** * 构造,相对于classes读取文件 * * @param path 相对路径 * @param clazz 基准类 * @param charset 字符集 */ public Props(String path, Class clazz, Charset charset) { Assert.notBlank(path, "Blank properties file path !"); if (null != charset) { this.charset = charset; } this.load(new ClassPathResource(path, clazz)); } /** * 构造,使用URL读取 * * @param propertiesUrl 属性文件路径 */ public Props(URL propertiesUrl) { this(propertiesUrl, StandardCharsets.ISO_8859_1); } /** * 构造,使用URL读取 * * @param propertiesUrl 属性文件路径 * @param charsetName 字符集 */ public Props(URL propertiesUrl, String charsetName) { this(propertiesUrl, CharsetUtil.charset(charsetName)); } /** * 构造,使用URL读取 * * @param propertiesUrl 属性文件路径 * @param charset 字符集 */ public Props(URL propertiesUrl, Charset charset) { Assert.notNull(propertiesUrl, "Null properties URL !"); if (null != charset) { this.charset = charset; } this.load(propertiesUrl); } /** * 构造,使用URL读取 * * @param properties 属性文件路径 */ public Props(Properties properties) { if (MapUtil.isNotEmpty(properties)) { this.putAll(properties); } } // ----------------------------------------------------------------------- 构造方法 end /** * 初始化配置文件 * * @param url {@link URL} * @since 5.5.2 */ public void load(URL url) { load(new UrlResource(url)); } /** * 初始化配置文件 * * @param resource {@link Resource} */ public void load(Resource resource) { Assert.notNull(resource, "Props resource must be not null!"); this.resource = resource; try (final BufferedReader reader = resource.getReader(charset)) { super.load(reader); } catch (IOException e) { throw new IORuntimeException(e); } } /** * 重新加载配置文件 */ public void load() { this.load(this.resource); } /** * 在配置文件变更时自动加载 * * @param autoReload 是否自动加载 */ public void autoLoad(boolean autoReload) { if (autoReload) { Assert.notNull(this.resource, "Properties resource must be not null!"); if (null != this.watchMonitor) { // 先关闭之前的监听 this.watchMonitor.close(); } this.watchMonitor = WatchUtil.createModify(this.resource.getUrl(), new SimpleWatcher() { @Override public void onModify(WatchEvent event, Path currentPath) { load(); } }); this.watchMonitor.start(); } 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 getEnum(Class clazz, String key, E defaultValue) { return Convert.toEnum(clazz, getStr(key), defaultValue); } @Override public > E getEnum(Class clazz, String key) { return getEnum(clazz, key, null); } @Override public Date getDate(String key, Date defaultValue) { return Convert.toDate(getStr(key), defaultValue); } @Override public Date getDate(String key) { return getDate(key, null); } /** * 获取并删除键值对,当指定键对应值非空时,返回并删除这个值,后边的键对应的值不再查找 * * @param keys 键列表,常用于别名 * @return 字符串值 * @since 4.1.21 */ public String getAndRemoveStr(String... keys) { Object value = null; for (String key : keys) { value = remove(key); if (null != value) { break; } } return (String) value; } /** * 转换为标准的{@link Properties}对象 * * @return {@link Properties}对象 * @since 5.7.4 */ public Properties toProperties() { final Properties properties = new Properties(); properties.putAll(this); return properties; } /** * 将配置文件转换为Bean,支持嵌套Bean
* 支持的表达式: * *
	 * persion
	 * persion.name
	 * persons[3]
	 * person.friends[5].name
	 * ['person']['friends'][5]['name']
	 * 
* * @param Bean类型 * @param beanClass Bean类 * @return Bean对象 * @since 4.6.3 */ public T toBean(Class beanClass) { return toBean(beanClass, null); } /** * 将配置文件转换为Bean,支持嵌套Bean
* 支持的表达式: * *
	 * persion
	 * persion.name
	 * persons[3]
	 * person.friends[5].name
	 * ['person']['friends'][5]['name']
	 * 
* * @param Bean类型 * @param beanClass Bean类 * @param prefix 公共前缀,不指定前缀传null,当指定前缀后非此前缀的属性被忽略 * @return Bean对象 * @since 4.6.3 */ public T toBean(Class beanClass, String prefix) { final T bean = ReflectUtil.newInstanceIfPossible(beanClass); return fillBean(bean, prefix); } /** * 将配置文件转换为Bean,支持嵌套Bean
* 支持的表达式: * *
	 * persion
	 * persion.name
	 * persons[3]
	 * person.friends[5].name
	 * ['person']['friends'][5]['name']
	 * 
* * @param Bean类型 * @param bean Bean对象 * @param prefix 公共前缀,不指定前缀传null,当指定前缀后非此前缀的属性被忽略 * @return Bean对象 * @since 4.6.3 */ public T fillBean(T bean, String prefix) { prefix = StrUtil.nullToEmpty(StrUtil.addSuffixIfNot(prefix, StrUtil.DOT)); String key; for (java.util.Map.Entry entry : this.entrySet()) { key = (String) entry.getKey(); if (false == StrUtil.startWith(key, prefix)) { // 非指定开头的属性忽略掉 continue; } try { BeanUtil.setProperty(bean, StrUtil.subSuf(key, prefix.length()), entry.getValue()); } catch (Exception e) { // 忽略注入失败的字段(这些字段可能用于其它配置) StaticLog.debug("Ignore property: [{}],because of: {}", key, e); } } return bean; } // ----------------------------------------------------------------------- Get end // ----------------------------------------------------------------------- Set start /** * 设置值,无给定键创建之。设置后未持久化 * * @param key 属性键 * @param value 属性值 */ public void setProperty(String key, Object value) { super.setProperty(key, value.toString()); } /** * 持久化当前设置,会覆盖掉之前的设置 * * @param absolutePath 设置文件的绝对路径 * @throws IORuntimeException IO异常,可能为文件未找到 */ public void store(String absolutePath) throws IORuntimeException { Writer writer = null; try { writer = FileUtil.getWriter(absolutePath, charset, false); super.store(writer, null); } catch (IOException e) { throw new IORuntimeException(e, "Store properties to [{}] error!", absolutePath); } finally { IoUtil.close(writer); } } /** * 存储当前设置,会覆盖掉以前的设置 * * @param path 相对路径 * @param clazz 相对的类 */ public void store(String path, Class clazz) { this.store(FileUtil.getAbsolutePath(path, clazz)); } // ----------------------------------------------------------------------- Set end }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy