mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:37:59 +08:00
Props add toBean method
This commit is contained in:
parent
9228a195b5
commit
9ed6412bac
@ -10,6 +10,7 @@
|
||||
* 【extra】 邮件增加图片支持(pr#495@Github)
|
||||
* 【core】 MapUtil、CollUtil增加emptyIfNull(issue#502@Github)
|
||||
* 【core】 增加emptyIfNull等(issue#503@Github)
|
||||
* 【setting】 Props增加toBean方法(issue#499@Github)
|
||||
|
||||
### Bug修复
|
||||
* 【http】 修复HttpRquest中body方法长度计算问题(issue#I10UPG@Gitee)
|
||||
|
@ -236,7 +236,10 @@ public class ReflectUtil {
|
||||
public static void setFieldValue(Object obj, String fieldName, Object value) throws UtilException {
|
||||
Assert.notNull(obj);
|
||||
Assert.notBlank(fieldName);
|
||||
setFieldValue(obj, getField(obj.getClass(), fieldName), value);
|
||||
|
||||
final Field field = getField(obj.getClass(), fieldName);
|
||||
Assert.notNull(field, "Field [{}] is not exist in [{}]", fieldName, obj.getClass().getName());
|
||||
setFieldValue(obj, field, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -249,7 +252,7 @@ public class ReflectUtil {
|
||||
*/
|
||||
public static void setFieldValue(Object obj, Field field, Object value) throws UtilException {
|
||||
Assert.notNull(obj);
|
||||
Assert.notNull(field);
|
||||
Assert.notNull(field, "Field in [{}] not exist !", obj.getClass().getName());
|
||||
field.setAccessible(true);
|
||||
|
||||
if(null != value) {
|
||||
|
@ -1,9 +1,11 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
@ -13,7 +15,7 @@
|
||||
<artifactId>hutool-setting</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>Hutool 配置文件增强</description>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
@ -25,5 +27,11 @@
|
||||
<artifactId>hutool-log</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -14,6 +14,7 @@ import java.nio.file.WatchEvent;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.getter.BasicTypeGetter;
|
||||
@ -31,9 +32,11 @@ import cn.hutool.core.io.watch.WatchMonitor;
|
||||
import cn.hutool.core.io.watch.WatchUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.log.Log;
|
||||
import cn.hutool.log.LogFactory;
|
||||
import cn.hutool.log.StaticLog;
|
||||
import cn.hutool.setting.SettingRuntimeException;
|
||||
|
||||
/**
|
||||
@ -57,9 +60,9 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
* 获得Classpath下的Properties文件
|
||||
*
|
||||
* @param resource 资源(相对Classpath的路径)
|
||||
* @return Properties
|
||||
* @return Props
|
||||
*/
|
||||
public static Properties getProp(String resource) {
|
||||
public static Props getProp(String resource) {
|
||||
return new Props(resource);
|
||||
}
|
||||
|
||||
@ -70,7 +73,7 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
* @param charsetName 字符集
|
||||
* @return Properties
|
||||
*/
|
||||
public static Properties getProp(String resource, String charsetName) {
|
||||
public static Props getProp(String resource, String charsetName) {
|
||||
return new Props(resource, charsetName);
|
||||
}
|
||||
|
||||
@ -81,7 +84,7 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
* @param charset 字符集
|
||||
* @return Properties
|
||||
*/
|
||||
public static Properties getProp(String resource, Charset charset) {
|
||||
public static Props getProp(String resource, Charset charset) {
|
||||
return new Props(resource, charset);
|
||||
}
|
||||
|
||||
@ -120,7 +123,7 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
*/
|
||||
public Props(String path, Charset charset) {
|
||||
Assert.notBlank(path, "Blank properties file path !");
|
||||
if(null != charset) {
|
||||
if (null != charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
this.load(ResourceUtil.getResourceObj(path));
|
||||
@ -187,7 +190,7 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
*/
|
||||
public Props(String path, Class<?> clazz, Charset charset) {
|
||||
Assert.notBlank(path, "Blank properties file path !");
|
||||
if(null != charset) {
|
||||
if (null != charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
this.load(new ClassPathResource(path, clazz));
|
||||
@ -220,7 +223,7 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
*/
|
||||
public Props(URL propertiesUrl, Charset charset) {
|
||||
Assert.notNull(propertiesUrl, "Null properties URL !");
|
||||
if(null != charset) {
|
||||
if (null != charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
this.load(new UrlResource(propertiesUrl));
|
||||
@ -276,7 +279,7 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
// 先关闭之前的监听
|
||||
this.watchMonitor.close();
|
||||
}
|
||||
this.watchMonitor = WatchUtil.createModify(this.propertiesFileUrl, new SimpleWatcher(){
|
||||
this.watchMonitor = WatchUtil.createModify(this.propertiesFileUrl, new SimpleWatcher() {
|
||||
@Override
|
||||
public void onModify(WatchEvent<?> event, Path currentPath) {
|
||||
load();
|
||||
@ -441,17 +444,17 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
public <E extends Enum<E>> E getEnum(Class<E> 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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取并删除键值对,当指定键对应值非空时,返回并删除这个值,后边的键对应的值不再查找
|
||||
*
|
||||
@ -469,6 +472,86 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
}
|
||||
return (String) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将配置文件转换为Bean,支持嵌套Bean<br>
|
||||
* 支持的表达式:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* ['person']['friends'][5]['name']
|
||||
* </pre>
|
||||
*
|
||||
* @param beanClass Bean类
|
||||
* @return Bean对象
|
||||
* @since 4.6.3
|
||||
*/
|
||||
public <T> T toBean(Class<T> beanClass) {
|
||||
return toBean(beanClass, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将配置文件转换为Bean,支持嵌套Bean<br>
|
||||
* 支持的表达式:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* ['person']['friends'][5]['name']
|
||||
* </pre>
|
||||
*
|
||||
* @param beanClass Bean类
|
||||
* @param prefix 公共前缀,不指定前缀传null,当指定前缀后非此前缀的属性被忽略
|
||||
* @return Bean对象
|
||||
* @since 4.6.3
|
||||
*/
|
||||
public <T> T toBean(Class<T> beanClass, String prefix) {
|
||||
final T bean = ReflectUtil.newInstanceIfPossible(beanClass);
|
||||
return fillBean(bean, prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将配置文件转换为Bean,支持嵌套Bean<br>
|
||||
* 支持的表达式:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* ['person']['friends'][5]['name']
|
||||
* </pre>
|
||||
*
|
||||
* @param bean Bean对象
|
||||
* @param prefix 公共前缀,不指定前缀传null,当指定前缀后非此前缀的属性被忽略
|
||||
* @return Bean对象
|
||||
* @since 4.6.3
|
||||
*/
|
||||
public <T> T fillBean(T bean, String prefix) {
|
||||
prefix = StrUtil.addSuffixIfNot(prefix, StrUtil.DOT);
|
||||
|
||||
String key;
|
||||
for (java.util.Map.Entry<Object, Object> 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: [{}]", key);
|
||||
}
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- Get end
|
||||
|
||||
@ -489,7 +572,7 @@ public final class Props extends Properties implements BasicTypeGetter<String>,
|
||||
* @param absolutePath 设置文件的绝对路径
|
||||
* @throws IORuntimeException IO异常,可能为文件未找到
|
||||
*/
|
||||
public void store(String absolutePath) throws IORuntimeException{
|
||||
public void store(String absolutePath) throws IORuntimeException {
|
||||
Writer writer = null;
|
||||
try {
|
||||
writer = FileUtil.getWriter(absolutePath, charset, false);
|
||||
|
@ -1,5 +1,8 @@
|
||||
package cn.hutool.setting.test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
@ -8,37 +11,76 @@ import org.junit.Test;
|
||||
import cn.hutool.log.LogFactory;
|
||||
import cn.hutool.log.dialect.console.ConsoleLogFactory;
|
||||
import cn.hutool.setting.dialect.Props;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Setting单元测试
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class PropsTest {
|
||||
|
||||
|
||||
@Before
|
||||
public void init(){
|
||||
public void init() {
|
||||
LogFactory.setCurrentLogFactory(ConsoleLogFactory.class);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void propTest(){
|
||||
public void propTest() {
|
||||
Props props = new Props("test.properties");
|
||||
String user = props.getProperty("user");
|
||||
Assert.assertEquals(user, "root");
|
||||
|
||||
|
||||
String driver = props.getStr("driver");
|
||||
Assert.assertEquals(driver, "com.mysql.jdbc.Driver");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void propTestForAbsPAth() {
|
||||
Props props = new Props("d:/test.properties");
|
||||
String user = props.getProperty("user");
|
||||
Assert.assertEquals(user, "root");
|
||||
|
||||
String driver = props.getStr("driver");
|
||||
Assert.assertEquals(driver, "com.mysql.jdbc.Driver");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void propTestForAbsPAth(){
|
||||
Props props = new Props("d:/test.properties");
|
||||
String user = props.getProperty("user");
|
||||
Assert.assertEquals(user, "root");
|
||||
public void toBeanTest() {
|
||||
Props props = Props.getProp("to_bean_test.properties");
|
||||
|
||||
String driver = props.getStr("driver");
|
||||
Assert.assertEquals(driver, "com.mysql.jdbc.Driver");
|
||||
ConfigProperties cfg = props.toBean(ConfigProperties.class, "mail");
|
||||
Assert.assertEquals("mailer@mail.com", cfg.getHost());
|
||||
Assert.assertEquals(9000, cfg.getPort());
|
||||
Assert.assertEquals("mailer@mail.com", cfg.getFrom());
|
||||
|
||||
Assert.assertEquals("john", cfg.getCredentials().getUsername());
|
||||
Assert.assertEquals("password", cfg.getCredentials().getPassword());
|
||||
Assert.assertEquals("SHA1", cfg.getCredentials().getAuthMethod());
|
||||
|
||||
Assert.assertEquals("true", cfg.getAdditionalHeaders().get("redelivery"));
|
||||
Assert.assertEquals("true", cfg.getAdditionalHeaders().get("secure"));
|
||||
|
||||
Assert.assertEquals("admin@mail.com", cfg.getDefaultRecipients().get(0));
|
||||
Assert.assertEquals("owner@mail.com", cfg.getDefaultRecipients().get(1));
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ConfigProperties {
|
||||
private String host;
|
||||
private int port;
|
||||
private String from;
|
||||
private Credentials credentials;
|
||||
private List<String> defaultRecipients;
|
||||
private Map<String, String> additionalHeaders;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Credentials {
|
||||
private String authMethod;
|
||||
private String username;
|
||||
private String password;
|
||||
}
|
||||
}
|
||||
|
20
hutool-setting/src/test/resources/to_bean_test.properties
Normal file
20
hutool-setting/src/test/resources/to_bean_test.properties
Normal file
@ -0,0 +1,20 @@
|
||||
#Simple properties
|
||||
mail.host=mailer@mail.com
|
||||
mail.port=9000
|
||||
mail.from=mailer@mail.com
|
||||
|
||||
#List properties
|
||||
mail.defaultRecipients[0]=admin@mail.com
|
||||
mail.defaultRecipients[1]=owner@mail.com
|
||||
|
||||
#Map Properties
|
||||
mail.additionalHeaders.redelivery=true
|
||||
mail.additionalHeaders.secure=true
|
||||
|
||||
#Object properties
|
||||
mail.credentials.username=john
|
||||
mail.credentials.password=password
|
||||
mail.credentials.authMethod=SHA1
|
||||
|
||||
# ignore properties
|
||||
mail.ignore.filed = balabala
|
Loading…
Reference in New Issue
Block a user