1. Apache Configuration简介
Apache configuration是一个用来读取配置文件的Apache开源库。可以读取多种配置文件,包括xml,properties,plist 等。
主要通过Configuration接口,对配置文件进行读写(自动进行类型转换)。具体方法如下:
同时,提供了很多configuration的实现类:
- properties文件--PropertiesConfiguration类
- xml文件--XMLConfiguration
- .ini文件--INIConfiguration
- .plist文件--PropertyListConfiguration
- 还可以从JNDI中读取properties--JNDIConfiguration
- 当然还可以使用system的properties--SystemConfiguration
- DataBaseConfiguration -- 从数据库中读取配置
- SubsetConfiguration--子集配置
- CompositeConfiguration -- 复合配置(可包括多个配置信息源)
2.读写配置(以xml 和 Properties为例)
读取Properties:
//注意路径默认指向的是classpath的根目录
Configuration config = new PropertiesConfiguration("te/test.properties");
String ip=config.getString("ip");
int port=config.getInt("port");
String title=config.getString("application.title");
在读取配置文件的时候有可能这个键值对应的值为空,那么在下面这个方法中
比如下面这个例子就会在test.properties这个文件中找id的值,如果找不到就会给id设置值为123
这样就保证了java的包装类不会返回空值。虽然功能很简单,但是很方便很实用。
Integer id=config.getInteger("id", new Integer(123));
如果在properties 文件中有如下属性keys=cn,com,org,uk,edu,jp,hk
可以实用下面的方式读取:
String[] keys1=config.getStringArray("keys");
List keys2=config.getList("keys");
读取xml:
XMLConfiguration config = new XMLConfiguration("XMLtest.xml");
/**
*<colors>
* <background>#808080</background>
* <text>#000000</text>
* <header>#008000</header>
* <link normal="#000080" visited="#800080"/>
* <default>${colors.header}</default>
*</colors>
*
*colors是根标签下的直接子标签,所以是顶级名字空间
*/
String backColor = config.getString("colors.background");
String textColor = config.getString("colors.text");
//如何读标签中的属性呢?看下面
//<link normal="#000080" visited="#800080"/>
String linkNormal = config.getString("colors.link[@normal]");
//还支持引用呢!
//<default>${colors.header}</default>
String defColor = config.getString("colors.default");
//也支持其他类型,但是一定要确定类型正确,否则要报异常哦
//<rowsPerPage>15</rowsPerPage>
int rowsPerPage = config.getInt("rowsPerPage");
3. 项目中使用Configuration
(1) 拓展Configuration实现类:
public class ConfigurationImpl extends CompositeConfiguration implements Configuration, InitializingBean {
private DatabaseConfiguration databaseConfiguration;
private org.apache.commons.configuration.Configuration staticConfiguration = StaticConfigurationSupplier .getConfiguration();
//添加多个Configuration配置源:(在初始化Configuration中调用)
public void setDatabaseConfiguration(DatabaseConfiguration databaseConfiguration) {
this.databaseConfiguration = databaseConfiguration;
removeConfiguration(staticConfiguration); //初始化是从xml中读取,后面移除再添加
addConfiguration(this.databaseConfiguration); //添加数据库配置
addConfiguration(staticConfiguration); //添加xml配置源
}
}
(2)启动时候初始化配置:
public class ConfigConfigurer {
@Autowired
private DatabaseConfigurationSource databaseConfigurationSource;
@Autowired
private Configuration configuration;
@PostConstruct
public void init() {
DatabaseConfiguration settingConfiguration = databaseConfigurationSource.getSource("setting");
((ConfigurationImpl) configuration).setDatabaseConfiguration(settingConfiguration);
((ConfigurationImpl) configuration).addConfiguration(settingConfiguration);
}
}
(3) 静态配置:
StaticConfigurationSupplier.java //根据不同的配置文件,返回一个复合的配置源,从配置源中查找时,先顺序查找,找不到时查找下一个配置
public static CombinedConfiguration getConfiguration() {
if (CONFIGURATION == null) {
try {
CombinedConfiguration combinedConfig = new CombinedConfiguration();
combinedConfig.setNodeCombiner(new OverrideCombiner());
for (String configLocation : _configLocations) {
AbstractConfiguration subConfig = null;
if (StringUtils.endsWith(configLocation, ".xml")) {
subConfig = new XMLConfiguration(new ClassPathResource(configLocation).getPath());
} else if (StringUtils.endsWith(configLocation, ".plist")) {
subConfig = new PropertyListConfiguration(new ClassPathResource(configLocation).getPath());
} else if (StringUtils.endsWith(configLocation, ".properties")) {
subConfig = new PropertiesConfiguration(new ClassPathResource(configLocation).getPath());
} else {
throw new IllegalStateException("unsupport configuration file type '"
+ FilenameUtils.getExtension(configLocation) + '"');
}
if (subConfig instanceof FileConfiguration) {
((FileConfiguration) subConfig).setAutoSave(false);
}
combinedConfig.addConfiguration(subConfig);
}
combinedConfig.setForceReloadCheck(false);
CONFIGURATION = combinedConfig;
_frozen = true;
} catch (ConfigurationException ex) {
throw new RuntimeException(ex);
}
}
return CONFIGURATION;
}
(4)简化读取层次:
如core.p 直接用p读取,使用SubsetConfiguration来封装作为Configuration的实现类:
public class SubsetConfiguration extends org.apache.commons.configuration.SubsetConfiguration implements Configuration {
public SubsetConfiguration(org.apache.commons.configuration.Configuration parent, String prefix) {
super(parent, prefix, ".");
}
@Override
public <T> T getProperty(String key, Class<T> targetType) {
Configuration parent = (Configuration)getParent();
return parent.getProperty(getParentKey(key), targetType);
}
}
(5)抽象的ConfigurationBean:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.base.Strings;
public abstract class ConfigurationBean implements InitializingBean {
@Autowired
private Configuration configuration;
private Configuration delegate;
private String subset;
public ConfigurationBean() {
}
public ConfigurationBean(String subset) {
this.subset = subset;
}
@Override
public void afterPropertiesSet() throws Exception {
if (Strings.isNullOrEmpty(this.subset)) { //没有前缀,使用Configuration的其他实现类(可能是DatabaseConfiguration或者statisticConfiguration等)
delegate = configuration;
} else {
delegate = new SubsetConfiguration(configuration, subset); //有前缀,使用前面提到的SubsetConfiguration
}
}
public Object getProperty(String key) {
return delegate.getProperty(key);
}
public <T> T getProperty(String key, Class<T> targetType) {
return delegate.getProperty(key, targetType);
}
public Configuration getDelegate() {
return delegate;
}
public String getSubset() {
return subset;
}
}
(6)其他地方使用:(作为服务接口)
@Component
public class TmPriceConfig extends ConfigurationBean{
public TmPriceConfig() {
super("trademarkPrice");
}
public Double getServiceFee() {
return getDelegate().getDouble("serviceFee");
}
public Double getOfficalFee() {
return getDelegate().getDouble("officalFee");
}
public Integer getLimitAmount() {
return getDelegate().getInt("limitAmount");
}
public Double getOverAmountFee() {
return getDelegate().getDouble("overAmountFee");
}
}
(7)如果要保存在数据库中,需要添加DatabaseConfiguration源:定义一个Bean,在bean初始化后进行
@PostConstruct
public void init() {
((ConfigurationImpl) configuration).addConfiguration(databaseConfigurationSource.getSource("trademarkPrice"));
}