对于java程序员来说各种各样的配置文件是司空见惯的,比如spring的bean配置,struts的action配置等等。有些配置会随着运行环境的变化而各不相同,最典型的就是jdbc驱动的配置,在开发环境可能链接到开发本地的数据库,测试环境则有一套测试专用的数据库环境,线上的生产环境也会有一套数据库,如果一个应用要部署到多个idc中,那这些配置又有可能各不相同。解决这个问题,可能有些团队使用同一份配置文件,在部署到不同的环境之前人肉的修改一下配置,还有些团队会为每一个环境维护一份配置文件。这些做法都比较容易出错,而且随着环境的增多成本会线性地增长。
本文通过一个示例简单介绍一个自动化的配置工具autoconfig。autoconfig使用一套配置模板,为不同的环境生成相应的具体配置。它的核心思想是把一些可变的配置定义为一个模板,在autoconfig运行的时候从这些模板中生成具体的配置文件。autoconfig支持两种运行方式,第一种是作为普通的java应用程序从命令行来调用,另一种是作为maven的插件来运行。本文通过一个maven项目展示一下如何在maven中使用autoconfig。
autoconfig是一个淘宝开源的web框架webx的一个工具包,svn地址为 http://code.taobao.org/svn/webx/citrus-tool/trunk/,使用之前先checkout源代码本地安装一下,当然感兴趣的同学也可已研究一下它的源代码。安装非常简单,在checkout的源代码的根目录下运行 mvn clean install -Dmaven.test.skip。由于autoconfig使用maven build,安装之前必须先安装maven,不知到如何安装maven的同学可以google一下。
创建antoconfig的描述文件auto-config.xml以及配置文件config.properties的模板config.properties.vm。
config.properties的模板内容如下,它只有一行配置。
key = ${net_kiminotes_value}
antoconfig的描述文件auto-config.xml内容如下。
<config> <group> <property name="net.kiminotes.value" /> </group> <script> <generate template="config.properties.vm" destfile="config.properties" charset="utf-8" /> </script> </config>
property元素定义了一个需要autoconfig配置的属性 net.kiminotes.value。group元素把不同类库的property进行分组,这里仅配置了一个group。generate定义了一个配置文件生成策略,template属性定义了配置文件的的模板,destfile定义了生成后配置文件的存放位置。
注: 有人或许会感觉迷惑,在模板文件config.properties.vm中,需要被替换的明明是net_kiminotes_value,为什么在auto-config.xml文件中会定义属性 net.kiminotes.value 呢?现在只需要记住属性名中的点在autoconfig执行的时候会被替换成下划线,具体原因会在后续的blog中解释。
最后在pom中配置一下maven autoconfig插件,整个pom文件如下。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.kiminotes</groupId> <artifactId>autoconfig</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <build> <plugins> <plugin> <groupId>com.alibaba.citrus.tool</groupId> <artifactId>maven-autoconfig-plugin</artifactId> <version>1.0.9</version> <executions> <!-- 配置在package phase中运行maven-autoconfig-plugin的autoconfig goal --> <execution> <id>config</id> <goals> <goal>autoconfig</goal> </goals> <phase>package</phase> </execution> </executions> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <!-- 打出的jar包中的 MANIFEST.MF 文件中增加 Main-Class 这一项配置,这样就能在命令行中通过 java -jar 来执行打出的jar包 --> <manifestEntries> <Main-Class>net.kiminotes.Main</Main-Class> </manifestEntries> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <target>1.6</target> <source>1.6</source> </configuration> </plugin> </plugins> </build> </project>
在配置文件的模板 config.properties.vm 中有一个配置变量 ${net_kiminotes_value} 在执行autoconfig的时候需要被替换,那怎么给这个配置项赋值呢?autoconfig提供了两种方式来给配置变量赋值第一从java属性文件中读取第二是交互式地编辑。autoconfig首先读取当前工作目录的antx.properties文件,如果没有则读取${user.home}/antx.properties文件,如果这个文件也不存在,autoconfig就会启动交互式编辑器请求用户输入配置变量的值,如果配置变量的值是不完整的autoconfig则会立即停止配置并抛出一个异常。如果java属性文件的位置不在autoconfig默认的位置可以通过参数autoconfig.userProperties进行配置。处于简单其间,我们在当前目录新建一个java属性文件antx.properties,这个文件中定义了配置变量${net_kiminotes_value}的值。antx.properties 文件的内容如下。
net.kiminotes.value = hello, world
整个项目的结构如下所示:
下面运行maven来build这个项目。运行 mvn package,在target目录下生成一个jar包autoconfig-1.0-SNAPSHOT.jar,运行这个jar包。