
com.feilong.core.util.ResourceBundleUtil Maven / Gradle / Ivy
Show all versions of feilong Show documentation
/*
* Copyright (C) 2008 feilong
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.feilong.core.util;
import static com.feilong.core.Validator.isNotNullOrEmpty;
import static com.feilong.core.Validator.isNullOrEmpty;
import static com.feilong.core.lang.ObjectUtil.defaultIfNull;
import static com.feilong.core.lang.StringUtil.EMPTY;
import static com.feilong.core.lang.reflect.ConstructorUtil.newInstance;
import static java.util.Collections.emptyMap;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.TreeMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.feilong.core.Validate;
import com.feilong.core.bean.BeanUtil;
import com.feilong.core.bean.ConvertUtil;
import com.feilong.core.text.MessageFormatUtil;
import com.feilong.lib.lang3.StringUtils;
/**
* {@link java.util.ResourceBundle ResourceBundle} 工具类.
*
*
* 该类专注于解析配置文件,至于解析到的结果你可以使用 {@link ConvertUtil}来进行转换成你需要的类型
*
*
* 如果现在多种资源文件一起出现,该如何访问?
*
*
*
* 如果一个项目中同时存在Message.properties、Message_zh_CN.properties、Message_zh_ CN.class 3个类型的文件,那最终使用的是哪一个?
* 只会使用一个,按照优先级使用.
* 顺序为Message_zh_CN.class、Message_zh_CN.properties、Message.properties.
*
*
*
* 解析原理,参见:
* java.util.ResourceBundle#loadBundle(CacheKey, List, Control, boolean)
* {@link java.util.ResourceBundle.Control#newBundle(String, Locale, String, ClassLoader, boolean)}
*
*
*
* @author feilong
* @see MessageFormatUtil#format(String, Object...)
* @see java.util.ResourceBundle
* @see java.util.PropertyResourceBundle
* @see java.util.ListResourceBundle
* @see "org.springframework.core.io.support.LocalizedResourceHelper"
* @since 1.4.0
*/
public final class ResourceBundleUtil{
/** The Constant LOGGER. */
private static final Logger LOGGER = LoggerFactory.getLogger(ResourceBundleUtil.class);
/** Don't let anyone instantiate this class. */
private ResourceBundleUtil(){
//AssertionError不是必须的. 但它可以避免不小心在类的内部调用构造器. 保证该类在任何情况下都不会被实例化.
//see 《Effective Java》 2nd
throw new AssertionError("No " + getClass().getName() + " instances for you!");
}
//---------------------------------------------------------------
/**
* 获取resourceBundle
配置文件指定 key
键的值.
*
* 说明:
*
*
* - 支持配置文件含参数信息
arguments
,使用 {@link MessageFormatUtil#format(String, Object...)} 来解析
*
*
*
* 示例:
*
*
*
*
* 如果有配置文件 messages\feilong-core-test.properties,内容如下:
*
*
*
* test.arguments=my name is {0},age is {1}
*
*
*
* 此时调用方法:
*
*
*
* ResourceBundle resourceBundle = ResourceBundle.getBundle("messages/feilong-core-test");
* ResourceBundleUtil.getValueWithArguments(resourceBundle, "test.arguments", "feilong", "18");
*
*
* 返回:
*
*
* my name is feilong,age is 18
*
*
*
*
* @param resourceBundle
* the resource bundle
* @param key
* Properties配置文件键名
* @param arguments
* 此处可以传递Object[]数组过来
* @return 如果配置文件中,key不存在,LOGGER.warn警告输出,并返回 {@link StringUtils#EMPTY}
* @throws NullPointerException
* 如果 resourceBundle
或者 key
是null
* @throws IllegalArgumentException
* 如果 key
是blank,抛出 {@link IllegalArgumentException}
* @see java.util.ResourceBundle#getString(String)
* @see MessageFormatUtil#format(String, Object...)
* @since 1.8.1 support arguments param
*/
public static String getValue(ResourceBundle resourceBundle,String key,Object...arguments){
Validate.notNull(resourceBundle, "resourceBundle can't be null!");
Validate.notBlank(key, "key can't be null/empty!");
if (!resourceBundle.containsKey(key)){
LOGGER.warn("resourceBundle:[{}] don't containsKey:[{}]", resourceBundle, key);
return EMPTY;
}
//---------------------------------------------------------------
String value = resourceBundle.getString(key);
if (isNullOrEmpty(value)){
LOGGER.trace("resourceBundle has key:[{}],but value is null/empty", key);
}
return isNullOrEmpty(value) ? EMPTY : MessageFormatUtil.format(value, arguments);// 支持 arguments 为null,原样返回
}
//---------------------------------------------------------------
/**
* 解析 baseNamess
成map.
*
* 说明:
*
*
* - JDK默认使用的是{@link java.util.PropertyResourceBundle},内部是使用 hashmap来存储数据的,
* 本方法出于log以及使用方便,返回的是 TreeMap
* - 后面的配置文件会覆盖前面的配置文件
* - 如果文件不存在,将会被忽略
*
*
*
* 示例:
*
*
*
*
* 在 classpath messages 目录下面有 memcached.properties,内容如下:
*
*
*
* # 注意此处 ip出现 - 横杆 仅作测试使用
* memcached.serverlist=172.20.3-1.23:11211,172.20.31.22:11211
* memcached.poolname=sidsock2
* #单位分钟
* memcached.expiretime=180
*
* memcached.serverweight=2
*
* memcached.initconnection=10
* memcached.minconnection=5
* memcached.maxconnection=250
*
* #设置主线程睡眠时间,每30秒苏醒一次,维持连接池大小
* memcached.maintSleep=30
*
* #关闭套接字缓存
* memcached.nagle=false
*
* #连接建立后的超时时间
* memcached.socketto=3000
* memcached.alivecheck=false
*
*
*
* 此时你可以如此调用代码:
*
*
*
* Map{@code } map = toMap("messages/memcached");
* LOGGER.debug(JsonUtil.format(map));
*
*
* 返回:
*
*
* {
* "memcached.alivecheck": "false",
* "memcached.expiretime": "180",
* "memcached.initconnection": "10",
* "memcached.maintSleep": "30",
* "memcached.maxconnection": "250",
* "memcached.minconnection": "5",
* "memcached.nagle": "false",
* "memcached.poolname": "sidsock2",
* "memcached.serverlist": "172.20.3-1.23:11211,172.20.31.22:11211",
* "memcached.serverweight": "2",
* "memcached.socketto": "3000"
* }
*
*
*
*
* @param baseNames
* 一个或者多个完全限定类名,配置文件的包+类全名,比如 message.feilong-core-test (不要尾缀);
* 但是,为了和早期版本兼容,也可使用路径名来访问,比如message/feilong-core-test(使用 "/")
* @return 如果 baseNames
是null,抛出 {@link NullPointerException}
* 如果 baseNames
是empty,抛出 {@link IllegalArgumentException}
*
* 如果 baseNames
中有元素是null,抛出 {@link NullPointerException}
* 如果 baseNames
中有元素是blank,抛出 {@link IllegalArgumentException}
* 否则,解析所有的key和value转成 {@link TreeMap}
* @since 3.0.0
*/
public static Map toMap(String...baseNames){
Validate.notEmpty(baseNames, "baseNames can't be null/empty!");
//---------------------------------------------------------------
Map map = new TreeMap<>();//为了log方便,使用 treeMap
for (String baseName : baseNames){
Validate.notBlank(baseName, "baseName is null or empty,[%s]", ConvertUtil.toString(baseNames, ","));
//---------------------------------------------------------------
try{
ResourceBundle resourceBundle = getResourceBundle(baseName);
Map littleMap = toMap(resourceBundle);
if (isNotNullOrEmpty(littleMap)){
map.putAll(littleMap);
}
}catch (Exception e){
LOGGER.warn("baseName:[{}],message:[{}],ignore~", baseName, e.getMessage());
}
}
return map;
}
/**
* 将 resourceBundle
转成map.
*
* 说明:
*
*
* - JDK默认使用的是{@link java.util.PropertyResourceBundle},内部是使用 hashmap来存储数据的,
* 本方法出于log以及使用方便,返回的是 TreeMap
*
*
*
* 示例:
*
*
*
*
* 在 classpath messages 目录下面有 memcached.properties,内容如下:
*
*
*
* # 注意此处 ip出现 - 横杆 仅作测试使用
* memcached.serverlist=172.20.3-1.23:11211,172.20.31.22:11211
* memcached.poolname=sidsock2
* #单位分钟
* memcached.expiretime=180
*
* memcached.serverweight=2
*
* memcached.initconnection=10
* memcached.minconnection=5
* memcached.maxconnection=250
*
* #设置主线程睡眠时间,每30秒苏醒一次,维持连接池大小
* memcached.maintSleep=30
*
* #关闭套接字缓存
* memcached.nagle=false
*
* #连接建立后的超时时间
* memcached.socketto=3000
* memcached.alivecheck=false
*
*
*
* 此时你可以如此调用代码:
*
*
*
* Map{@code } map = toMap(getResourceBundle("messages/memcached"));
* LOGGER.debug(JsonUtil.format(map));
*
*
* 返回:
*
*
* {
* "memcached.alivecheck": "false",
* "memcached.expiretime": "180",
* "memcached.initconnection": "10",
* "memcached.maintSleep": "30",
* "memcached.maxconnection": "250",
* "memcached.minconnection": "5",
* "memcached.nagle": "false",
* "memcached.poolname": "sidsock2",
* "memcached.serverlist": "172.20.3-1.23:11211,172.20.31.22:11211",
* "memcached.serverweight": "2",
* "memcached.socketto": "3000"
* }
*
*
*
*
* @param resourceBundle
* the resource bundle
* @return 如果 resourceBundle
是null,抛出 {@link NullPointerException}
* 如果 resourceBundle
没有key,则返回{@link java.util.Collections#emptyMap()}
* 否则,解析所有的key和value转成 {@link TreeMap}
* @since 1.8.8
*/
public static Map toMap(ResourceBundle resourceBundle){
Validate.notNull(resourceBundle, "resourceBundle can't be null!");
Enumeration keysEnumeration = resourceBundle.getKeys();
if (isNullOrEmpty(keysEnumeration)){
return emptyMap();
}
//---------------------------------------------------------------
Map map = new TreeMap<>();//为了log方便,使用 treeMap
while (keysEnumeration.hasMoreElements()){
String key = keysEnumeration.nextElement();
map.put(key, resourceBundle.getString(key));
}
return map;
}
/**
* 将 resourceBundle
转成Properties.
*
* 示例:
*
*
*
*
* 在 classpath messages 目录下面有 memcached.properties,内容如下:
*
*
*
* # 注意此处 ip出现 - 横杆 仅作测试使用
* memcached.serverlist=172.20.3-1.23:11211,172.20.31.22:11211
* memcached.poolname=sidsock2
* #单位分钟
* memcached.expiretime=180
*
* memcached.serverweight=2
*
* memcached.initconnection=10
* memcached.minconnection=5
* memcached.maxconnection=250
*
* #设置主线程睡眠时间,每30秒苏醒一次,维持连接池大小
* memcached.maintSleep=30
*
* #关闭套接字缓存
* memcached.nagle=false
*
* #连接建立后的超时时间
* memcached.socketto=3000
* memcached.alivecheck=false
*
*
*
* 此时你可以如此调用代码:
*
*
*
* Properties properties = ResourceBundleUtil.toProperties("messages.memcached");
* LOGGER.debug(JsonUtil.format(properties));
*
*
* 返回:
*
*
* {
* "memcached.serverlist": "172.20.3-1.23:11211,172.20.31.22:11211",
* "memcached.maxconnection": "250",
* "memcached.socketto": "3000",
* "memcached.initconnection": "10",
* "memcached.nagle": "false",
* "memcached.expiretime": "180",
* "memcached.maintSleep": "30",
* "memcached.alivecheck": "false",
* "memcached.serverweight": "2",
* "memcached.poolname": "sidsock2",
* "memcached.minconnection": "5"
* }
*
*
*
*
* @param resourceBundle
* the resource bundle
* @return 如果 resourceBundle
没有key value,则返回 new Properties
* 否则,解析所有的key和value转成 {@link Properties}
* @throws NullPointerException
* 如果 resourceBundle
是null
* @see #toMap(ResourceBundle)
* @see ConvertUtil#toProperties(Map)
* @since 1.8.8
*/
public static Properties toProperties(ResourceBundle resourceBundle){
return ConvertUtil.toProperties(toMap(resourceBundle));
}
/**
* 将 resourceBundle
转换成aliasBean
.
*
* 示例:
*
*
*
*
* 在 classpath messages 目录下面有 memcached.properties,内容如下:
*
*
*
* # 注意此处 ip出现 - 横杆 仅作测试使用
* memcached.serverlist=172.20.3-1.23:11211,172.20.31.22:11211
* memcached.poolname=sidsock2
* #单位分钟
* memcached.expiretime=180
*
* memcached.serverweight=2
*
* memcached.initconnection=10
* memcached.minconnection=5
* memcached.maxconnection=250
*
* #设置主线程睡眠时间,每30秒苏醒一次,维持连接池大小
* memcached.maintSleep=30
*
* #关闭套接字缓存
* memcached.nagle=false
*
* #连接建立后的超时时间
* memcached.socketto=3000
* memcached.alivecheck=false
*
*
*
*
* 有以下aliasBean信息:
*
*
*
*
* public class DangaMemCachedConfig{
*
* //** The serverlist.
* @Alias(name = "memcached.serverlist",sampleValue = "172.20.31.23:11211,172.20.31.22:11211")
* private String[] serverList;
*
* //@Alias(name = "memcached.poolname",sampleValue = "sidsock2")
* private String poolName;
*
* //** The expire time 单位分钟.
* @Alias(name = "memcached.expiretime",sampleValue = "180")
* private Integer expireTime;
*
* //** 权重.
* @Alias(name = "memcached.serverweight",sampleValue = "2,1")
* private Integer[] weight;
*
* //** The init connection.
* @Alias(name = "memcached.initconnection",sampleValue = "10")
* private Integer initConnection;
*
* //** The min connection.
* @Alias(name = "memcached.minconnection",sampleValue = "5")
* private Integer minConnection;
*
* //** The max connection.
* @Alias(name = "memcached.maxconnection",sampleValue = "250")
* private Integer maxConnection;
*
* //** 设置主线程睡眠时间,每30秒苏醒一次,维持连接池大小.
* @Alias(name = "memcached.maintSleep",sampleValue = "30")
* private Integer maintSleep;
*
* //** 关闭套接字缓存.
* @Alias(name = "memcached.nagle",sampleValue = "false")
* private Boolean nagle;
*
* //** 连接建立后的超时时间.
* @Alias(name = "memcached.socketto",sampleValue = "3000")
* private Integer socketTo;
*
* //** The alive check.
* @Alias(name = "memcached.alivecheck",sampleValue = "false")
* private Boolean aliveCheck;
*
* //setter getter 略
* }
*
*
*
* 此时你可以如此调用代码:
*
*
*
* DangaMemCachedConfig dangaMemCachedConfig = ResourceBundleUtil.toAliasBean("messages.memcached", DangaMemCachedConfig.class);
* LOGGER.debug(JsonUtil.format(dangaMemCachedConfig));
*
*
* 返回:
*
*
* {
* "maxConnection": 250,
* "expireTime": 180,
* "serverList": [
* "172.20.3-1.23",
* "11211",
* "172.20.31.22",
* "11211"
* ],
* "weight": [2],
* "nagle": false,
* "initConnection": 10,
* "aliveCheck": false,
* "poolName": "sidsock2",
* "maintSleep": 30,
* "socketTo": 3000,
* "minConnection": 5
* }
*
*
*
* 你会发现类型会自动转换,虽然properties里面存储key和value都是string,但是使用该方法,可以自动类型转换,转成bean里面声明的类型
*
*
*
* 但是同时,你也会发现,上面的 serverList 期望值是 ["172.20.3-1.23:11211","172.20.31.22:11211"],但是和你的期望值不符合,
* 因为, {@link com.feilong.lib.beanutils.converters.ArrayConverter} 默认允许的字符 allowedChars 只有 '.', '-'
,其他都会被做成分隔符
*
*
*
* 你需要如此这般:
*
*
*
* ArrayConverter arrayConverter = new ArrayConverter(String[].class, new StringConverter(), 2);
* char[] allowedChars = { ':' };
* arrayConverter.setAllowedChars(allowedChars);
*
* ConvertUtils.register(arrayConverter, String[].class);
*
* DangaMemCachedConfig dangaMemCachedConfig = ResourceBundleUtil.toAliasBean("messages.memcached", DangaMemCachedConfig.class);
* LOGGER.debug(JsonUtil.format(dangaMemCachedConfig));
*
*
* 返回:
*
*
* {
* "maxConnection": 250,
* "expireTime": 180,
* "serverList": [
* "172.20.3-1.23:11211",
* "172.20.31.22:11211"
* ],
* "weight": [2],
* "nagle": false,
* "initConnection": 10,
* "aliveCheck": false,
* "poolName": "sidsock2",
* "maintSleep": 30,
* "socketTo": 3000,
* "minConnection": 5
* }
*
*
*
*
* @param
* the generic type
* @param resourceBundle
* the resource bundle
* @param aliasBeanClass
* the alias bean class
* @return the t
* @throws NullPointerException
* 如果 resourceBundle
或者 aliasBean
是null
* @see BeanUtil#populateAliasBean(Object, Map)
* @since 1.8.8
*/
public static T toAliasBean(ResourceBundle resourceBundle,Class aliasBeanClass){
Validate.notNull(resourceBundle, "resourceBundle can't be null/empty!");
Validate.notNull(aliasBeanClass, "aliasBeanClass can't be null!");
return BeanUtil.populateAliasBean(newInstance(aliasBeanClass), toMap(resourceBundle));
}
/**
* 读取 baseName
转换成bean
.
*
* 注意:
*
*
* - 配置文件key要和bean 属性一一对应
*
*
*
* 示例:
*
*
*
*
* 在 classpath messages 目录下面有 memcached.properties,内容如下:
*
*
*
* # 注意此处 ip出现 - 横杆 仅作测试使用
* serverList=172.20.3-1.23:11211,172.20.31.22:11211
* memcached.minconnection=5
* memcached.maxconnection=250
* #关闭套接字缓存
* memcached.nagle=false
*
*
*
* 有以下aliasBean信息:
*
*
*
*
* public class DangaMemCachedNoAliasConfig{
*
private String[] serverList;
private Integer initConnection;
private Integer minConnection;
private Boolean nagle;
*
* //setter getter 略
* }
*
*
*
* 此时你可以如此调用代码:
*
*
*
* DangaMemCachedNoAliasConfig config = ResourceBundleUtil.toBean("messages/memcachedBean", DangaMemCachedNoAliasConfig.class);
* LOGGER.debug(JsonUtil.format(config));
*
*
* 返回:
*
*
[
maxConnection=250
minConnection=5
nagle=false
serverList={172.20.3-1.23,11211,172.20.31.22,11211}
]
*
*
*
* 你会发现类型会自动转换,虽然properties里面存储key和value都是string,但是使用该方法,可以自动类型转换,转成bean里面声明的类型
*
*
*
* 但是同时,你也会发现,上面的 serverList 期望值是 ["172.20.3-1.23:11211","172.20.31.22:11211"],但是和你的期望值不符合,
* 因为, {@link com.feilong.lib.beanutils.converters.ArrayConverter} 默认允许的字符 allowedChars 只有 '.', '-'
,其他都会被做成分隔符
*
*
*
* 你需要如此这般:
*
*
*
* ArrayConverter arrayConverter = new ArrayConverter(String[].class, new StringConverter(), 2);
* char[] allowedChars = { ':' };
* arrayConverter.setAllowedChars(allowedChars);
*
* ConvertUtils.register(arrayConverter, String[].class);
*
* DangaMemCachedNoAliasConfig dangaMemCachedConfig = ResourceBundleUtil
* .toBean("messages/memcachedBean", DangaMemCachedNoAliasConfig.class);
* LOGGER.debug(JsonUtil.format(dangaMemCachedConfig));
*
*
* 返回:
*
*
* {
* "maxConnection": 250,
* "serverList": [
* "172.20.3-1.23:11211",
* "172.20.31.22:11211"
* ],
* "minConnection": 5
* }
*
*
*
*
* @param
* the generic type
* @param baseName
* 一个完全限定类名,配置文件的包+类全名,比如 message.feilong-core-test (不要尾缀);
* 但是,为了和早期版本兼容,也可使用路径名来访问,比如message/feilong-core-test(使用 "/")
* @param beanClass
* the alias bean class
* @return the t
* @throws NullPointerException
* 如果 baseName
或者 beanClass
是null
* @throws IllegalArgumentException
* 如果 baseName
是空
* @see BeanUtil#populateAliasBean(Object, Map)
* @since 4.0.1
*/
public static T toBean(String baseName,Class beanClass){
Validate.notEmpty(baseName, "baseName can't be null/empty!");
Validate.notNull(beanClass, "beanClass can't be null!");
ResourceBundle resourceBundle = getResourceBundle(baseName);
return toBean(resourceBundle, beanClass);
}
/**
* 读取 resourceBundle
转换成bean
.
*
* 注意:
*
*
* - 配置文件key要和bean 属性一一对应
*
*
*
* 示例:
*
*
*
*
* 在 classpath messages 目录下面有 memcached.properties,内容如下:
*
*
*
* # 注意此处 ip出现 - 横杆 仅作测试使用
* serverList=172.20.3-1.23:11211,172.20.31.22:11211
* memcached.minconnection=5
* memcached.maxconnection=250
* #关闭套接字缓存
* memcached.nagle=false
*
*
*
* 有以下aliasBean信息:
*
*
*
*
* public class DangaMemCachedNoAliasConfig{
*
private String[] serverList;
private Integer initConnection;
private Integer minConnection;
private Boolean nagle;
*
* //setter getter 略
* }
*
*
*
* 此时你可以如此调用代码:
*
*
*
* DangaMemCachedNoAliasConfig config = ResourceBundleUtil.toBean("messages/memcachedBean", DangaMemCachedNoAliasConfig.class);
* LOGGER.debug(JsonUtil.format(config));
*
*
* 返回:
*
*
[
maxConnection=250
minConnection=5
nagle=false
serverList={172.20.3-1.23,11211,172.20.31.22,11211}
]
*
*
*
* 你会发现类型会自动转换,虽然properties里面存储key和value都是string,但是使用该方法,可以自动类型转换,转成bean里面声明的类型
*
*
*
* 但是同时,你也会发现,上面的 serverList 期望值是 ["172.20.3-1.23:11211","172.20.31.22:11211"],但是和你的期望值不符合,
* 因为, {@link com.feilong.lib.beanutils.converters.ArrayConverter} 默认允许的字符 allowedChars 只有 '.', '-'
,其他都会被做成分隔符
*
*
*
* 你需要如此这般:
*
*
*
* ArrayConverter arrayConverter = new ArrayConverter(String[].class, new StringConverter(), 2);
* char[] allowedChars = { ':' };
* arrayConverter.setAllowedChars(allowedChars);
*
* ConvertUtils.register(arrayConverter, String[].class);
*
* DangaMemCachedNoAliasConfig dangaMemCachedConfig = ResourceBundleUtil
* .toBean("messages/memcachedBean", DangaMemCachedNoAliasConfig.class);
* LOGGER.debug(JsonUtil.format(dangaMemCachedConfig));
*
*
* 返回:
*
*
* {
* "maxConnection": 250,
* "serverList": [
* "172.20.3-1.23:11211",
* "172.20.31.22:11211"
* ],
* "minConnection": 5
* }
*
*
*
*
* @param
* @param resourceBundle
* @param beanClass
* @return 如果 resourceBundle
是null,抛出 {@link NullPointerException}
* 如果 beanClass
是null,抛出 {@link NullPointerException}
* @since 4.0.1
*/
public static T toBean(ResourceBundle resourceBundle,Class beanClass){
Validate.notNull(resourceBundle, "resourceBundle can't be null/empty!");
Validate.notNull(beanClass, "beanClass can't be null!");
Map map = toMap(resourceBundle);
return BeanUtil.populate(newInstance(beanClass), map);
}
//----------------------------getResourceBundle-----------------------------------
/**
* 使用 {@link Locale#getDefault()} 获得{@link ResourceBundle}.
*
* 示例:
*
*
*
*
* 场景: 如项目的classpath下面有 messages/feilong-core-test.properties,内容如下
*
*
*
* config_test_array=5,8,7,6
* test.arguments=my name is {0},age is {1}
*
*
*
* 你可以使用以下代码来读取内容:
*
*
*
* ResourceBundle resourceBundle = getResourceBundle("messages/feilong-core-test");
* LOGGER.debug(JsonUtil.format(toMap(resourceBundle)));
*
*
* 返回:
*
*
* {
* "config_test_array": "5,8,7,6",
* "test.arguments": "my name is {0},age is {1}",
* }
*
*
*
*
* @param baseName
* 一个完全限定类名,配置文件的包+类全名,比如 message.feilong-core-test (不要尾缀);
* 但是,为了和早期版本兼容,也可使用路径名来访问,比如message/feilong-core-test(使用 "/")
* @return 如果资源文件 baseName
里面没有任何内容,返回不是null的 {@link ResourceBundle}
* @throws NullPointerException
* 如果 baseName
是null
* @throws IllegalArgumentException
* 如果 baseName
是 blank
* @throws MissingResourceException
* 如果资源文件 baseName
不存在
* @see java.util.Locale#getDefault()
* @see #getResourceBundle(String, Locale)
*/
public static ResourceBundle getResourceBundle(String baseName){
return getResourceBundle(baseName, null);
}
/**
* 使用 baseName
和 locale
获得{@link ResourceBundle}.
*
* 示例:
*
*
*
*
* 场景: 比如在 classpath 下面有 messages\feilong-archetypes_en.properties 和 messages\feilong-archetypes_zh_CN.properties
* 两个配置文件,内容如下
*
*
*
* messages\feilong-archetypes_en.properties
*
*
*
* feilong-archetypes.welcome=欢迎(简体)
*
*
*
* messages\feilong-archetypes_zh_CN.properties
*
*
*
* feilong-archetypes.welcome=欢迎(简体)
*
*
*
* 此时,我要读取 英文的配置文件,你可以这么写
*
*
*
* ResourceBundle resourceBundle = getResourceBundle("messages/feilong-archetypes", Locale.ENGLISH);
* Map{@code } map = toMap(resourceBundle);
*
* LOGGER.debug(JsonUtil.format(map));
*
*
* 返回:
*
*
* {"feilong-archetypes.welcome": "welcome(english)"}
*
*
*
*
* @param baseName
* 一个完全限定类名,配置文件的包+类全名,比如 message.feilong-core-test (不要尾缀);
* 但是,为了和早期版本兼容,也可使用路径名来访问,比如message/feilong-core-test(使用 "/")
* @param locale
* the locale for which a resource bundle is desired,如果是null,将使用 {@link Locale#getDefault()}
* @return 如果资源文件 baseName
里面没有任何内容,返回不是null的 {@link ResourceBundle}
* 如果是null,将使用 {@link Locale#getDefault()}来获取
* @throws NullPointerException
* 如果 baseName
是null
* @throws IllegalArgumentException
* 如果 baseName
是 blank
* @throws MissingResourceException
* 如果资源文件 baseName
不存在
* @see java.util.ResourceBundle#getBundle(String, Locale)
*/
public static ResourceBundle getResourceBundle(String baseName,Locale locale){
Validate.notBlank(baseName, "baseName can't be null/empty!");
return ResourceBundle.getBundle(baseName, defaultIfNull(locale, Locale.getDefault()));
}
//---------------------------------------------------------------
/**
* 获得ResourceBundle({@link PropertyResourceBundle}),新增这个方法的初衷是为了能读取任意的资源(包括本地file等).
*
* 示例:
*
*
*
*
* 场景: 有配置文件在 E:\\DataCommon\\Files\\Java\\config\\mail-read.properties (通常敏感的配置文件不会随着项目走),现在需要读取里面的信息
*
*
*
* ResourceBundle resourceBundle = getResourceBundle(
* FileUtil.getFileInputStream("E:\\DataCommon\\Files\\Java\\config\\mail-read.properties"));
* LOGGER.debug(JsonUtil.format(toMap(resourceBundle)));
*
*
* 返回:
*
*
* {
* "incoming.imap.hostname": "imap.exmail.qq.com",
* "incoming.pop.hostname": "pop.exmail.qq.com",
* }
*
*
*
*
* @param inputStream
* the input stream
* @return 如果 inputStream
是null,抛出 {@link NullPointerException}
* 否则返回 {@link java.util.PropertyResourceBundle#PropertyResourceBundle(InputStream)}
* @see java.util.PropertyResourceBundle#PropertyResourceBundle(InputStream)
* @since 1.0.9
*/
public static ResourceBundle getResourceBundle(InputStream inputStream){
Validate.notNull(inputStream, "inputStream can't be null!");
//---------------------------------------------------------------
try{
return new PropertyResourceBundle(inputStream);
}catch (IOException e){
throw new UncheckedIOException(e);
}finally{
try{
inputStream.close();
}catch (IOException e){
LOGGER.error("", e);
}
}
}
}