Maven下实现多种环境下的资源配置管理

构建项目时可能会遇到在测试(如单元测试)、开发、模拟、生产等不同环境下需要不同配置(properties、xml)或资源(jpg、png、mp3)的情况。比如常见的数据库连接(即 jdbc url)的值,在不同的环境下可能有如下几种值:

  • 测试环境:jdbc:mysql://localhost:3306/foobar_test
  • 开发环境:jdbc:mysql://localhost:3306/foobar_dev
  • 模拟环境:jdbc:mysql://192.168.1.11:3306/foobar
  • 生产环境:jdbc:mysql://192.168.1.10:3306/foobar

或者同样是生产环境,针对(产品)交付给A公司客户的与交付给B公司客户的需要不同配置或者资源,比如产品界面中的公司名称、公司LOGO等。

又或者针对不同的操作系统(如 Windows,Linux)需要为某个配置设定不同的文件路径。

可见,在不同的软件开发生命周期阶段、不同的最终客户(用户)环境、不同的运行平台都有可能需要不同配置或资源的情况。假如各个环境下的差别很小的话,我们可以在项目编译之后手工修改或者写个 shell script 自动修改,但如果需要修改的项目很多而且复杂的话,则应该使用 Apache Maven来管理。

 

有两种实现方式,

    第一种类似项目中使用的,定义三个文件:

        src/main/resources/config_DEV.properties

        src/main/resources/config_TEST.properties

        src/main/resources/config_PROD.properties

    项目中实际引用的是config.properties,通过maven-antrun-plugin来实现替换

    (ps:config.properties 文件不需要提前创建,编译时自动copy)

 

    第二种方式利用了maven的profile和filtering的功能,把上述步骤的直接替换改为过滤器来进行选择。缺点是,如果在其它配置文件中引用变量还可以,如果在java文件中读取需要指定文件名时还需要额外做判断,不灵活。

配置文件引用:
<bean id="uploadService" class="com.oist.project.service.UploadServiceImpl">
    <property name="uploadDir" value="${spring.uploadDir}"/>
  </bean>

   

原理可参考链接:

       http://archboy.org/2012/05/21/apache-maven-profile-filtering-multiple-build-environments/

    具体实现最好参考:

         http://blog.csdn.net/wangjunjun2008/article/details/11516323

        http://blog.csdn.net/wuxinzaiyu/article/details/8524274

        http://blog.csdn.net/crazycoder2010/article/details/7264644

 

  1. <build>  
  2.         <filters>  
  3.             <filter>src/main/resources/config_${env}.properties</filter>   //要过滤的文件路径、名称
  4.         </filters>  
  5.         <resources>  
  6.             <resource>  
  7.                 <directory>src/main/resources</directory>  //这个路径下的文件打开过滤
  8.                 <filtering>true</filtering>  
  9.             </resource>  
  10.         </resources>  
  11.   
  12.         ......  
  13.   
  14.     </build> 

这种方式需要提前创建好config.properties文件,且文件内容格式为:

jdbc.driverClassName=${jdbc.driverClassName}

jdbc.url=${jdbc.url}

jdbc.username=${jdbc.username}

jdbc.password=${jdbc.password}

编译后,占位符中内容将会被替换为实际值

 

    省事的方式是直接将属性定义在profile里,其它地方直接引用,变量多时比较臃肿,不建议

        <profile>

            <id>dev</id>

            <activation>

                <activeByDefault>true</activeByDefault>

            </activation>

            <properties>

                <redis.hostName>cache01.game.sogou-inc.com</redis.hostName>

                <redis.port>6380</redis.port>

                <jdbc.driver>com.p6spy.engine.spy.P6SpyDriver</jdbc.driver>

                <!--<jdbc.driver>com.mysql.jdbc.Driver</jdbc.driver>-->

                <logback.logLevel>debug</logback.logLevel>

                <static.resource>http://localhost</static.resource>

                <ime.push.online>false</ime.push.online>

            </properties>

        </profile>

在编译项目时,可以使用 -P 参数指定需要使用的 profile 的 id,比如下面命令将会使用 dev profile:

$mvn clean compile -Pdev
假如不指定 -P 参数的话,则会使用 activeByDefault=true 的一项

 如果代码中需要判断当前环境,一般通过获取本机ip地址做判断

 

还有第三种方式更简单,利用resin properties重写的功能,避免环境依赖,开发机、测试机、预发布机、线上机容器中分别配置对应的属性。

<context:property-placeholder order="0" location="classpath:app.properties"  system-properties-mode="OVERRIDE"/>

 

在resin配置文件/usr/local/resin/conf/resin.xml 中去配置app.properties中的参数

    <!-- Java system-properties -->

    <system-property mail.smtp.host="127.0.0.1"/>

    <system-property mail.smtp.port="25"/>

    <system-property spring.profiles.active="production"/>

 

    <system-property domain="api.app.wan.sogou.com"/>

 

    <system-property peak.api_server="http://up.sohu.com"/>

    <system-property peak.pub_server="https://up.sohu.com"/>

    <system-property peak.game_center_callback="http://api.app.wan.sogou.com/api/peak.do"/>

 

    <system-property midas.api_host="api.unipay.qq.com"/>

 

    <system-property db.game.host="mblgm01.dt.mysql.db"/>

    <system-property db.game.user="shouyou"/>

    <system-property db.game.password="shouyou!@#$"/>

 

    <system-property memcached.servers="10.11.211.101:11211"/>

 

    <system-property redis.host="redis01.shouyou.tc.vm"/>

 

    <system-property redis.port="6379"/>

 

外部配置

有时候有些关键的属性,比如数据库密码,需要放在xml文件之外,便于后续修改。Spring解决这个问题的方法有两种,一种是属性占位符,一种是属性重写。另外阿里提供的AutoConfig有更好的配置管理机制,将在后面详细介绍。

 

第一种:关于占位符,首先载入属性文件:

  1. <context:property-placeholder location="classpath:/db.properties"/>  
  2. 或者  
  3. <context:property-placeholder location="file:///etc/db.properties"/>  

 

引用属性中的变量:

  1. <bean id="dataSource" class="org.springframework.jdbc.datbase.DriverManagerDataSource">  
  2.   <property name="driverClassName" value="${jdbc.driverClassName}"/>  
  3.   <property name="url" value="${jdbc.url}/>  
  4. </bean>  

 

第二种:

(1)覆盖properties文件中的变量:

  1. <util:properties id="defConf>  
  2.   <prop key="jdbc.url">jdbc:mysql://localhost/test</prop>  
  3.   <prop key="jdbc.driverClassName">com.mysql.jdbc.Driver</prop>  
  4. </util:properties>  
  5.   
  6. <context:property-placeholder location="classpath:/db.properties" properties-ref="defConf" 
  7.     system-properties-mode="OVERRIDE"/>  
  8. 除了OVERRIDE还有FALLBACK、NEVER。  

这个就是上面的例子,通过resin配置文件修改了system properties。

 

 

(2) 覆盖xml配置。载入properties文件并覆盖现有的xml配置。请看下面的例子:

  1. <bean id="dataSource" class="xxx">  
  2.   <property name="url">jdbc:oracle://xxx</property>  
  3.   <property name="username">xxx</property>  
  4. </bean>  
  5.   
  6. <context:property-overrider location="classpath:/db.properties"/>  

这个用另一个文件替换了原来的文件

 

System Properties

In Properties, we examined the way an application can use Properties objects to maintain its configuration. The Java platform itself uses a Properties object to maintain its own configuration. The System class maintains a Properties object that describes the configuration of the current working environment. System properties include information about the current user, the current version of the Java runtime, and the character used to separate components of a file path name.

 

The following table describes some of the most important system properties

Key Meaning
   
"java.class.path" Path used to find directories and JAR archives containing class files. Elements of the class path are separated by a platform-specific character specified in the path.separator property.
"java.home" Installation directory for Java Runtime Environment (JRE)

 

Resin 中

<system-property>

child of resin,cluster,host,web-app

Sets a Java system property. The effect is the same as if you had called before starting Resin.

Example: setting system property
 
<resin>
  <system-property foo="bar"/>
</resin>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章