配置文件外化

2024-01-15 23:50
文章标签 配置文件 外化

本文主要是介绍配置文件外化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

  一般的web开发中,配置文件分为xml和properties两种。其中properties文件可能在java代码中读取使用,也可能在xml中读取使用,比如配置数据源。我们要尽量的把全部的properties和部分的xml配置文件外化出来。

静态工具类:    

    首先对于java中读取的properties文件我们可以提供一个工具类,供其他同事开发与使用。如果用一个Properties对象存储多个文件时会发生相同key值前者被后者覆盖掉的问题,为了能够更清晰的管理properties文件,这里采用每个文件对应一个Properties对象的方法,该工具类提供两个参数,取值时需要把文件名称和key都传进来。

  • 提供获取properties内容的工具类:
*** @description: 该工具类提供按照指定文件读取properties文件内的信息* @author: zhangchi* @email: zc_ciyuan@163.com* @datetime: 2017/1/14 13:45* @version: 1.0.0*/
public final class PropertiesUtil {private PropertiesUtil() {}/*** 日志引用*/private static final LogUtil logger = LogUtil.getInstance();/*** 根据properties文件名称和键获取对应值** @param propertiesName 文件名称* @param key            键* @return 返回value*/public static String getPropertiesByKey(String propertiesName, String key) {if (PropertiesLoader.propertiesMap != null) {return PropertiesLoader.propertiesMap.get(propertiesName).getProperty(key);} else {try {PropertiesLoader.loader();return PropertiesLoader.propertiesMap.get(propertiesName).getProperty(key);} catch (IOException e) {logger.error(null, "加载properties文件异常", "初始化配置文件", e);return null;}}}}
  • 这里加载制定路径下的配置文件:
/*** @description: 读取制定路径下的properties文件* @author: zhangchi* @email: zc_ciyuan@163.com* @datetime: 2017/1/14 13:49* @version: 1.0.0*/
public class PropertiesLoader {/*** 日志引用*/private static final LogUtil logger = LogUtil.getInstance();/*** 定义存入properties属性的map集合*/public static ConcurrentMap<String, Properties> propertiesMap = null;/*** 加载配置文件*/public static void loader() throws IOException {if (propertiesMap == null){propertiesMap = new ConcurrentHashMap<>();ResourcePatternResolver rpr = new PathMatchingResourcePatternResolver();InputStreamReader inputStreamReader = null;String path = ".././files/configuration/**/*.properties";try {/** 读取文件*/Resource[] resources = rpr.getResources(ResourceUtils.FILE_URL_PREFIX + path);for (Resource r : resources) {Properties properties = new Properties();logger.info("初始化配置文件:", r.getURL().toString(), null);inputStreamReader = new InputStreamReader(r.getInputStream(), "UTF-8");properties.load(inputStreamReader);propertiesMap.put(r.getFilename(), properties);}} catch (IOException e) {logger.error(null, "获取制定路径下的properties文件异常", "", e);} finally {if (inputStreamReader != null) {try {inputStreamReader.close();} catch (IOException e) {logger.error(null, "过去projects文件的InputStreamReader流关闭异常", "", e);}}}}}
}

    需要注意的是我们使用了spring的PathMatchingResourcePatternResolver类进行读取properties文件,通过使用通配符支持子目录文件查询。path路径采用的是相对路径方式,这里的“.././”就相当于在当前工作路径的上一级目录下要有个files目录来存放properties文件。./即系统参数${user.dir}如果不考虑运维其实可以通过创建一个环境变量来定义指定路径,这样无论是本地开发(通常是windows)还是生产环境(linux)只要定义了环境变量,那么我们就不需要更改代码中的路径了。在代码中完全可以通过System.getenv("XXX")来获取,个人建议通过环境变量来制定路径是对代码侵入最小的方式,我在这里只是用了相对路径而已。

Java Config配置

    以上的工具类只适用于java代码,那么如果xml中该如何读取需要的配置文件呢?spring支持通过file:/xxx/xx/x.properties这种方式制定读取文件。

<!-- <context:property-placeholder location="classpath*:props/*.properties" ignore-unresolvable="true"/>-->
<context:property-placeholder location="file:D:/files/**/*.properties" ignore-unresolvable="true"/>
  • 这里我讲通过使用java config的方式尽量的避免使用xml文件,比如通过java配置数据源、SpringMVC属性配置等:
/*** @description: 配置Druid数据源* @author: zhangchi* @email: zc_ciyuan@163.com* @datetime: 2017/1/16 9:43* @version: 1.0.0*/
@Configuration
public class DruidDataSourceConfig {/*** 配置数据源** @return dataSource* @throws SQLException 抛出SQL异常*///@Bean(name = "dataSource" , initMethod = "init",destroyMethod="close")public DruidDataSource druidDataSource() throws SQLException {DruidDataSource dds = new DruidDataSource();/*获取配置属性,初始化连接池*/String url = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.connectionURL");if (!Strings.isNullOrEmpty(url)) {dds.setUrl(url);}String userName = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.userId");if (!Strings.isNullOrEmpty(userName)) {dds.setUsername(userName);}String passWord = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.password");if (!Strings.isNullOrEmpty(passWord)) {dds.setPassword(passWord);}String initialSize = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.initialSize");if (!Strings.isNullOrEmpty(initialSize)) {dds.setInitialSize(Integer.parseInt(initialSize)); //初始化连接大小}String maxActive = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.maxActive");if (!Strings.isNullOrEmpty(maxActive)) {dds.setMaxActive(Integer.parseInt(maxActive)); //连接池最大使用连接数量}String maxIdle = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.maxIdle");if (!Strings.isNullOrEmpty(maxIdle)) {dds.setMaxIdle(Integer.parseInt(maxIdle)); //连接池最大空闲}String minIdle = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.minIdle");if (!Strings.isNullOrEmpty(minIdle)) {dds.setMinIdle(Integer.parseInt(minIdle)); //连接池最小空闲}String maxWait = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.maxWait");if (!Strings.isNullOrEmpty(maxWait)) {dds.setMaxWait(Long.parseLong(maxWait)); //获取连接最大等待时间}String validationQuery = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.validationQuery");if (!Strings.isNullOrEmpty(validationQuery)) {dds.setValidationQuery(validationQuery);}String testOnBorrow = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.testOnBorrow");if (!Strings.isNullOrEmpty(testOnBorrow)) {dds.setTestOnBorrow(Boolean.parseBoolean(testOnBorrow));}String testOnReturn = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.testOnReturn");if (!Strings.isNullOrEmpty(testOnReturn)) {dds.setTestOnReturn(Boolean.parseBoolean(testOnReturn));}String testWhileIdle = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.testWhileIdle");if (!Strings.isNullOrEmpty(testWhileIdle)) {dds.setTestWhileIdle(Boolean.parseBoolean(testWhileIdle));}String timeBetweenEvictionRunsMillis = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.timeBetweenEvictionRunsMillis");if (!Strings.isNullOrEmpty(timeBetweenEvictionRunsMillis)) {dds.setTimeBetweenEvictionRunsMillis(Long.parseLong(timeBetweenEvictionRunsMillis)); //配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒}String minEvictableIdleTimeMillis = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.minEvictableIdleTimeMillis");if (!Strings.isNullOrEmpty(minEvictableIdleTimeMillis)) {dds.setMinEvictableIdleTimeMillis(Long.parseLong(minEvictableIdleTimeMillis)); //配置一个连接在池中最小生存的时间,单位是毫秒}String removeAbandoned = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.removeAbandoned");if (!Strings.isNullOrEmpty(removeAbandoned)) {dds.setRemoveAbandoned(Boolean.parseBoolean(removeAbandoned)); //打开removeAbandoned功能}String removeAbandonedTimeout = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.removeAbandonedTimeout");if (!Strings.isNullOrEmpty(removeAbandonedTimeout)) {dds.setRemoveAbandonedTimeout(Integer.parseInt(removeAbandonedTimeout));}String logAbandoned = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.logAbandoned");if (!Strings.isNullOrEmpty(logAbandoned)) {dds.setLogAbandoned(Boolean.parseBoolean(logAbandoned)); //关闭abanded连接时输出错误日志}String filters = PropertiesUtil.getPropertiesByKey(Constants.PROPERTIES_NAME_JDBC, "jdbc.filters");if (!Strings.isNullOrEmpty(filters)) {dds.setFilters(filters); //监控数据库}dds.init();return dds;}/*** 创建SqlSessionFactoryBean工厂实例** @return SqlSessionFactoryBean* @throws IOException  加载myBatis文件失败时抛出* @throws SQLException 加载dataSource失败时抛出*/@Bean@Scope(value = "singleton")public SqlSessionFactoryBean sqlSessionFactory() throws IOException, SQLException {SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();sessionFactoryBean.setDataSource(druidDataSource());ResourcePatternResolver rpr = new PathMatchingResourcePatternResolver();Resource[] resources = rpr.getResources("classpath*:mybatis/mapper/*.xml");sessionFactoryBean.setMapperLocations(resources);return sessionFactoryBean;}/*** 创建MapperScannerConfigurer实例** @return MapperScannerConfigurer*/@Bean@Scope(value = "singleton")public MapperScannerConfigurer mapperScannerConfigurer() {MapperScannerConfigurer msc = new MapperScannerConfigurer();msc.setBasePackage("com.xxx.xxx.xxx.dal.dao");msc.setSqlSessionFactoryBeanName("sqlSessionFactory");return msc;}
/*** @description: 配置springMVC* @author: zhangchi* @email: zc_ciyuan@163.com* @datetime: 2017/1/18 16:20* @version: 1.0.0*/
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy(proxyTargetClass=true)//激活切面AOP
public class WebConfig extends WebMvcConfigurerAdapter {/** (non-Javadoc)* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter* #configureViewResolvers(* org.springframework.web.servlet.config.annotation.ViewResolverRegistry)* 配置视图解析翻译从控制器返回到具体的基于字符串的视图名称视图 实现执行与渲染。*/@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {registry.enableContentNegotiation(new MappingJackson2JsonView());registry.jsp("/WEB-INF/views/", ".jsp");//注册JSP视图解析器指定的前缀和后缀。}/** (non-Javadoc)* * @see* org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#addResourceHandlers(* org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry)* 添加处理程序服务静态资源,如图片,JS,并从其他受Web应用程序根目录的特定位置,类路径中,cssfiles。*/@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/styles/**").addResourceLocations("/styles/");registry.addResourceHandler("/scripts/**").addResourceLocations("/scripts/");registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");}/** (non-Javadoc)* * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter* #addViewControllers( org.springframework.web.servlet.config.annotation.ViewControllerRegistry)* * 配置视图控制器*/@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("/login");registry.addViewController("/login.do").setViewName("/login");registry.addViewController("/index.do").setViewName("/login/index");}@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {// Date to/from jsonObjectMapper objectMapper = new ObjectMapper();objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();converter.setObjectMapper(objectMapper);converters.add(converter);}
}

    虽然通过JavaConfig能够避免一些通过xml加载的容器项,但是这并不能避免所有的配置需求,比如使用dubbo时需要注册zookeeper。针对于其他XML中需要读取properties元素的配置我们可以把properties还是加载到Spring的Properties对象里,只不过这一步我们也是通过JavaConfig来实现的。实际上我们是讲所有的properties文件存了两份,一份在Spring中一份在我们的Map<Properties>集合中。

/*** @description: 加载properties文件* @author: zhangchi* @email: zc_ciyuan@163.com* @datetime: 2017/1/18 20:31* @version: 1.0.0*/
@Configuration
@PropertySources({@PropertySource(value = "file:.././files/configuration/common.properties",ignoreResourceNotFound = true,encoding = "UTF-8"),@PropertySource(value = "file:.././files/configuration/constant.properties",encoding = "UTF-8"),@PropertySource(value = "file:.././files/configuration/httpclient.properties"),@PropertySource(value = "file:.././files/configuration/jdbc.properties"),@PropertySource(value = "file:.././files/configuration/zookeeper.properties")
})
public class PropertiesConfig {@Beanpublic PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){return new PropertySourcesPlaceholderConfigurer();}
}

XML中正常注册zook

<dubbo:application name="dubbo-channel-service"/>
<dubbo:registry address="${zookeeper.url}"/>
<dubbo:protocol name="dubbo" port="${dubbo.port}"/>

web.xml外化配置

    部分配置文件是需要通过web.xml管理的例如logback.xml,web.xml中也可以指定加载路径。

<!--定义logback加载配置-->
<context-param><param-name>logbackConfigLocation</param-name><param-value>file:.././files/configuration/logback.xml</param-value>
</context-param><!--配置logback监听-->
<listener><listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
</listener>

总结:

    以上内容将web开发中常遇到的配置进行了外化,主要就是通过JavaConfig、工具类、file:指定路径等方式把配置文件放到我们指定的路径中,避免了打包时配置文件出现在我们的war包或jar包里。从而避免了每次修改配置文件都需要重新打包编译一次再发版的烦人问题。这里没有介绍具体的分布式配置中心实现方式,因为那将是一个大话题需要根据具体项目的业务场景决定,所以以上内容只适用于学习参考。

转载于:https://my.oschina.net/zhangshuge/blog/828875

这篇关于配置文件外化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/610620

相关文章

web群集--nginx配置文件location匹配符的优先级顺序详解及验证

文章目录 前言优先级顺序优先级顺序(详解)1. 精确匹配(Exact Match)2. 正则表达式匹配(Regex Match)3. 前缀匹配(Prefix Match) 匹配规则的综合应用验证优先级 前言 location的作用 在 NGINX 中,location 指令用于定义如何处理特定的请求 URI。由于网站往往需要不同的处理方式来适应各种请求,NGINX 提供了多种匹

前端-06-eslint9大变样后,如何生成旧版本的.eslintrc.cjs配置文件

目录 问题解决办法 问题 最近在写一个vue3+ts的项目,看了尚硅谷的视频,到了配置eslintrc.cjs的时候我犯了难,因为eslint从9.0之后重大更新,跟以前完全不一样,但是我还是想用和老师一样的eslintrc.cjs文件,该怎么做呢? 视频链接:尚硅谷Vue项目实战硅谷甄选,vue3项目+TypeScript前端项目一套通关 解决办法 首先 eslint 要

Centos9 网卡配置文件

1、Centos stream 9 网络介结 Centos以前版本,NetworkManage以ifcfg格式存储网络配置文件在/etc/sysconfig/networkscripts/目录中。但是,Centos steam 9现已弃用ifcfg格式,默认情况下,NetworkManage不再创建此格式的新配置文件。从Centos steam 9开始采用密钥文件格式(基于INI文件),Netw

【SpringMVC学习03】-SpringMVC的配置文件详解

在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。其实真正需要程序员开发的就两大块:一个是Handler,一个是jsp。 在springMVC的入门程序中,SpringMVC的核心配置文件——springmvc.xml为: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http:

python+selenium2轻量级框架设计-03读取配置文件

任何一个项目,都涉及到了配置文件和管理和读写,Python支持很多配置文件的读写,这里介绍读取ini文件。 以读取url和浏览器作为例子 #浏览器引擎类import configparser,time,osfrom selenium import webdriverfrom framework.logger import Loggerlogger = Logger(logger='

linux配置DNS解析设置之配置文件“/etc/resolv.conf “

在 Linux 系统中,/etc/resolv.conf 文件用于配置系统的 DNS 解析设置。它定义了如何将主机名(例如 www.example.com)转换为 IP 地址。主要功能包括: 主要功能 DNS 服务器地址:指定系统用于查询域名的 DNS 服务器。你可以在该文件中列出一个或多个 DNS 服务器的 IP 地址。 示例内容: conf 复制代码 nameserver 8.

centos7 网卡配置文件

1、Centos6与Centos7网络命令对照表 2、网络配置文件解释说明 静态IP配置: cat /etc/sysconfig/network-scripts/ifcfg-eth0 TYPE=Ethernet BOOTPROTO=static DEVICE=eth0 NAME=eth0 ONBOOT=yes IPADDR=192.168.10.250 NETMASK=255

SpringBoot整合Minio及阿里云OSS(配置文件无缝切换)

SpringBoot整合Minio及阿里云OSS 文章目录 SpringBoot整合Minio及阿里云OSS1.Minio安装测试1.Docker安装启动容器 2.创建bucket3.上传文件修改权限 2.SpringBoot整合Minio及阿里云OSS1.公共部分抽取2.Minio配置整合1.添加pom依赖2.添加配置文件3.操作接口实现 3.阿里云OSS配置整合1.pom依赖2.添加

maven打包成可执行的jar,以及读取配置文件问题小结

文章来源 https://blog.csdn.net/chasonsp/article/details/88852353 折腾的几天,使用maven打包后发现了问题,首先是打包的配置文件读取问题,使用getResource().getPah()会发现在访问jar包的文件时,路径里会有感叹号(杠杠滴~~)是这样的 …jar!.. 经过不断的查找资料及反复验证后,终于找到了可行的方法: