背景
- 当我们在服务器上安装一些软件服务时,如 MySQL、Kafka、ES 等,在启动服务的时候,脚本会读取默认路径下的配置文件,如果配置文件没有放到默认的路径下,我们也可以通过参数的方式指定,通过这个配置文件,可以灵活方便的开始某些功能或调整某些参数,不用重新对源码进行修改、编译和发布了。
- 所以,我们工作当中有时希望可以把配置文件放在程序外,这样就可以做到配置与业务分离,在项目中使用的 properties,这里就说一下如何用 properties 配置文件,默认加载 classpath 下的文件,如果通过参数指定了文件路径就可以使用外部配置了。
- 最近在使用 Netty 实现一个 TCP Server,主要用来接收媒体数据,然后对其进行相应的处理;同时,在这个项目中也嵌入了 HTTP 服务,使用 Jetty 实现了 HTTP Servlet,用来实现一些 Web 的交互控制。在这个项目中,服务的端口和一些开关设置使用了配置文件。
举例
在介绍完背景后,来看看是怎么来实现这样一个应用程序,此程序仅使用了 Netty 和 Jetty ,没有使用 Spring 相关的框架。本篇主要介绍如何实现读取外部配置文件
依赖
<dependency> <groupId>commons-configuration</groupId> <artifactId>commons-configuration</artifactId> <version>1.10</version> </dependency>
实现
lombok, 通过注解引入 log
单例模式
package com.xxx.config; import lombok.extern.log4j.Log4j2; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.configuration.SystemConfiguration; import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; import org.apache.commons.lang3.StringUtils; import java.io.File; @Log4j2 public class ConfigStrategy { private boolean autoReload; private static final String BASE_PATH; private static final String GLOBAL_CONFIG_PATH = "global.config.path"; private static final String fileName="conf.properties"; private static volatile PropertiesConfiguration prop =null; static{ log.info("start init configuration strategy"); SystemConfiguration sysConfig = new SystemConfiguration(); String globalPath = sysConfig.getString(GLOBAL_CONFIG_PATH); log.info("configuration globalPath {} ", globalPath); // 默认加载classpath下面的文件 if(StringUtils.isBlank(globalPath)){ globalPath = Thread.currentThread().getContextClassLoader().getResource(fileName).getFile(); } BASE_PATH=globalPath; } public ConfigStrategy(boolean autoReload) throws ConfigurationException { this.autoReload = autoReload; loadConfig(); } public void loadConfig() throws ConfigurationException { if (null == prop){ prop = new PropertiesConfiguration(); } File file = new File(BASE_PATH); prop.setFile(file); prop.setAutoSave(false); // 重载策略,5秒钟监视文件变化 if(autoReload){ prop.setReloadingStrategy(new FileChangedReloadingStrategy()); } prop.load(); } /** * 获取字符串类型的配置项 * * @param key * @return value */ public String getProperty(String key) { return prop.getString(key); } /** * 获取整数类型的配置项 * * @param key * @return value */ public Integer getInteger(String key) { String value = getProperty(key); return Integer.valueOf(value); } /** * 获取布尔类型的配置项 * * @param key * @return value */ public Boolean getBoolean(String key) { String value = getProperty(key); return Boolean.valueOf(value); } /** * 获取Long类型的配置项 * * @param key * @return */ public Long getLong(String key) { String value = getProperty(key); return Long.valueOf(value); } private static class SingletonHelp { static ConfigStrategy instance; static { try { instance = new ConfigStrategy(true); } catch (ConfigurationException e) { log.error("configuration strategy init error ", e); } } } public static ConfigStrategy build(){ return SingletonHelp.instance; } }
项目启动命令
-Dglobal.config.path
指定配置文件的位置注意
-Dglobal.config.path=./conf.properties
的顺序,在放到 xxxx.jar 前,否则读取不到配置文件。
java -jar -Dglobal.config.path=./conf.properties xxxx.jar