针对常见应用场景,可以分为以下几个方面来考虑
注意:本文只针对没有接入统一配置中心、配置平台的情况
一、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