针对常见应用场景,可以分为以下几个方面来考虑
注意:本文只针对没有接入统一配置中心、配置平台的情况
一、Java服务器端项目
1、对于项目的框架或者组件,如果支持编程方式配置,则编程根据不同环境读取不同配置,例如Spring框架、Logback日志库都支持;
1) 如果使用Spring Boot,直接采用官方推荐的配置切换方式:设置spring.profiles.active,可以是jvm变量、main启动参数、环境变量等(建议使用jvm变量);
2) 如果使用Spring框架(但是非Spring Boot),环境相关的配置参数放在properties文件中,写个工具类,就可以根据不同环境(建议根据jvm变量识别)读取对应properties;
3) 如果使用 logback,在非Spring Boot环境下,可以把配置参数放在properties文件中,根据不同环境(建议根据jvm变量识别)读取对应properties;在Spring Boot环境下,可以使用logback的springProperty标签获取spring托管的参数;
2、其他组件,如果不支持编程,(比如某些环境要引入一些特殊的二进制包,脚本,图片,或者xml文件等),则采用maven打包时输入-P参数选择打包指定文件达到目的。
二、客户端(Android、iOS、H5等)项目
1. 利用打包工具,在打包时自动区分各环境的配置文件。(无需人工手动替换)
下面就以上提到的某些方面进行说明
1、JVM变量、环境变量的配置
IDE工具:
可以直接在图形化的配置窗口(VM arguments 或 VM options)配置
IDEA配置JVM启动参数 参见: http://blog.csdn.net/wangnayu/article/details/76794112
Eclipse配置JVM启动参数 参见:https://jingyan.baidu.com/article/624e7459653ca534e8ba5a26.html
服务器JVM启动参数:
一般是在启动脚本或者配置脚本里面添加。
TOMCAT JVM启动参数配置 :在catalina.bat或catalina.sh里面设置,参见: http://blog.csdn.net/xinluke/article/details/51490048
系统环境变量设置:
1)Windows,参见:https://jingyan.baidu.com/article/d5a880eb6aca7213f047cc6c.html
2)Linux,有多种方式,参见:http://www.cnblogs.com/answercard/p/7142448.html
2、Maven打包切换配置的方法(适用于Log4j 等组件的配置)
如果组件自身不支持以编程的方式进行配置,则可以借助打包工具,maven、gradle等,下面以maven为例说明。用法参见:https://my.oschina.net/u/2341924/blog/667730
3、Spring 的配置方法
在Spring 非 Spring Boot环境下,方案如下:
(1) 尽量将配置都交给Spring管理(可以通过注入bean方式或者@Value等方式获取配置的值);
(2) 将Spring的配置参数,都集中在一个或者多个properties文件中,并将环境相关的配置 分环境单独放置在后缀为"-dev"、"-test"、"-prod"...的properties文件中;
配置切换方式一:
利用Spring的spring.profiles.active参数来配置,例如:
<beans profile="dev">
<!-- 开发环境 -->
<context:property-placeholder location="classpath:jdbc-dev.properties,classpath:conf.properties"/>
</beans>
<beans profile="sit">
<!-- 测试sit环境 -->
<context:property-placeholder location="classpath:jdbc-sit.properties,classpath:conf.properties"/>
</beans>
<beans profile="uat">
<!-- 测试uat环境 -->
<context:property-placeholder location="classpath:jdbc-uat.properties,classpath:conf.properties"/>
</beans>
<beans profile="pre">
<!-- 预发布环境 -->
<context:property-placeholder location="classpath:jdbc-pre.properties,classpath:conf.properties"/>
</beans>
<beans profile="prod">
<!-- 生产环境 -->
<context:property-placeholder location="file:${java.home}/jdbc-prod.properties,classpath:conf.properties"/>
</beans>配置方式二:(推荐)
扩展spring的properties加载类org.springframework.beans.factory.config.PropertyPlaceholderConfigurer,使其能够根据不同的环境读取不同的properties配置文件,关于这个小工具,已经写好了,只需要在项目中引入即可,maven坐标如下:
<!-- 用法参见http://10.2.10.22/zollty/zollty-commons/tree/master/zollty-common-util --> <dependency> <groupId>com.zollty.commons</groupId> <artifactId>zollty-common-util</artifactId> <version>最新版本</version> </dependency>
配置好后就可以直接使用了,例如,在Spring的xml配置文件中可以像下面这么配置:
<bean id="confProperties" class="io.zollty.util.EnvirmentPropertyConfigurer">
<property name="globalLocations">
<list> <!-- 全局配置 -->
<value>classpath:conf.properties</value>
<value>classpath:dubbo/consumer.properties</value>
</list>
</property>
<!-- 分为 dev sit uat pre prod等环境 -->
<property name="environmentLocations">
<map> <!-- 环境相关配置,文件后缀'.properties'省略,'classpath:'也可以省略 -->
<entry key="dev" value="classpath:conf-dev" />
<entry key="sit" value="classpath:conf-sit,file:C:/Users/consumer"/>
<entry key="uat" value="file:${java.home}/conf-uat"/>
<entry key="pre" value="file:${java.home}/conf-pre"/>
<entry key="prod" value="file:${java.home}/conf-prod"/>
<!-- dev为默认配置。切换其他配置,需要设置参数,例如JVM参数 -Dspring.profiles.active=test -->
<!-- 支持多个文件逗号分隔 -->
<!-- 支持系统\环境变量占位符 -->
<!-- 支持'file:'前缀从文件系统读取文件 -->
</map>
</property>
<!-- 这个配置是可选的,设置为true代表 找不到配置时 不报错(默认为null),否则会报错提示 -->
<property name="ignoreUnresolvablePlaceholders" value="false"/>
</bean>使用时,可以在classpath下面放置如下一些配置文件:
conf.properties(全局配置)
conf-dev.properties(开发环境的配置)
conf-sit.properties(测试环境SIT的配置)
conf-uat.properties(测试环境UAT的配置)
conf-prod.properties(生产环境的配置)
conf-demoxxx.properties(其他分类配置)
dubbo/consumer.properties(其他分类配置)
这个工具默认会读取全局配置,环境默认读取dev下面的配置,如果想切换到测试环境的配置,可以配置JVM系统变量:
-Dspring.profiles.active=test
或者操作系统的环境变量也可以。
这样配置的话,生效的就是 test 环境对应的配置。
4、Logback的配置方法
logback也支持多种方式扩展,一种是在logback.xml配置中使用条件表达式判断,第二种方法是使用statusListener,在logback配置解析之前调用一个自定义的类来设置参数。
下面给出配置示例:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 这个工具类参见:http://10.2.10.22/zollty/zollty-commons/tree/master/zollty-common-util -->
<statusListener class="io.zollty.util.InitLogConfigListener" />
<!-- 部署的环境类型:dev、test、product -->
<property name="DEPLOY_ENV" value="${deploy.env:-dev}" />
<!-- 日志路径,这里是相对路径,web项目eclipse下会输出到当前目录./logs/下,如果部署到linux上的tomcat下,会输出到tomcat/logs/目录 下 -->
<property name="LOG_HOME" value="${catalina.base:-.}/logs" />
<!-- 日志文件大小,超过这个大小将被压缩 -->
<property name="LOG_MAX_SIZE" value="100MB" />
<!-- 日志输出格式 -->
<property name="LOG_COMMON_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] [%level] %logger - %msg%n" />
<property name="LOG_DEV_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{48}:%line - %msg%n" />
<!-- 主日志级别 -->
<property name="ROOT_LEVEL" value="${log.root.level:-DEBUG}" />
<!-- APP 日志级别 -->
<property name="APP_LEVEL" value="${log.app.level:-TRACE}" />
<!-- APP Package 前缀: cn.zollty.lightning -->
<property name="APP_PACKAGE" value="cn.zollty.lightning" />
<include resource="includedConfig.xml"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_DEV_PATTERN}</pattern>
</encoder>
</appender>
<appender name="FILTER-DATA" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/filter.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/filter/filter-%d{yyyy-MM-dd}-%i.log.zip</fileNamePattern>
<maxHistory>90</maxHistory>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>100MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${LOG_COMMON_PATTERN}</pattern>
</encoder>
</appender>
<appender name="ASYNC1" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILTER-DATA" />
</appender>
<include resource="special_log_level.xml"/>
<logger name="${APP_PACKAGE}" level="${APP_LEVEL}" />
<logger name="FILTER-LOGGER" level="${APP_LEVEL}" additivity="false">
<appender-ref ref="ASYNC1" />
</logger>
<root level="${ROOT_LEVEL}">
<!-- Required: exception log -->
<appender-ref ref="FILE_EXCEPTION"/>
<!-- Required: app log -->
<appender-ref ref="FILE_APP"/>
<!-- Optional: show all debug or trace info -->
<!-- <appender-ref ref="FILE_DEBUG"/> -->
<!-- <appender-ref ref="FILE_TRACE"/> -->
<if condition='p("DEPLOY_ENV").contains("dev")'>
<then>
<appender-ref ref="STDOUT" />
</then>
</if>
</root>
</configuration>这个配置的关键之处在于系统变量、环境变量的条件表达式的使用:
1、
<!-- 部署的环境类型deploy.env = dev、test、product -->
<property name="DEPLOY_ENV" value="${deploy.env:-dev}" />
2、
<!-- 主日志级别 -->
<property name="ROOT_LEVEL" value="${log.root.level:-DEBUG}" />
<!-- APP 日志级别 -->
<property name="APP_LEVEL" value="${log.app.level:-TRACE}" />
3、
<if condition='p("DEPLOY_ENV").contains("dev")'>
<then>
<appender-ref ref="STDOUT" />
</then>
</if>
5、编程方式自动读取配置(以Logback为例)
上面说到,有一些组件是支持以编程方式来配置的,logback就支持,方法是在logback.xml配置如下标签:
<statusListener class="io.zollty.util.InitLogConfigListener" />
在这个类InitLogConfigListener中,就可以任意发挥了,例如可以从jvm变量中获取值。这个工具类参见:
http://10.2.10.22/zollty/zollty-commons/tree/master/zollty-common-util