`

maven AutoConfig工具原理

阅读更多

需求

在一个应用中,我们总是会遇到一些参数,例如:

数据库服务器IP地址、端口、用户名。

用来保存上传资料的目录。

这些参数有一个共性,那就是:它们和应用的逻辑无关,只和当前环境、当前系统用户相关。

 

常见场景

在开发、测试、发布阶段,使用不同的数据库服务器。

在开发阶段,使用Windows的A开发者将用户上传的文件存放在d:\my_upload目录中,而使用Linux的B开发者将同样的文件存放在/home/myname/my_upload目录中。

很明显,这些参数不适合被“硬编码”在配置文件或代码中。因为每一个从源码库中取得它们的人,都有可能需要修改它们,使之与自己的环境相匹配。

 

解决方案

运行时替换的placeholders

很多框架支持在运行时刻替换配置文件中的placeholder占位符。

例如, Webx/Spring就有这个功能。

在Webx中定义placeholders

<services:property-placeholder />

<services:webx-configuration>

    <services:productionMode>${productionMode:true}</services:productionMode>

</services:webx-configuration>

在上面这个例子中,你可以在启动应用时,加上JVM参数:“-DproductionMode=false|true”来告诉系统用哪一种模式来工作。如果不指定,则取默认值“true”。

 

优点

配置文件是静态的、不变的。即使采用不同的参数值,你也不需要更改配置文件本身。

你可以随时改变参数的值,只需要启动时指定不同的JVM参数、或指定不同的properties文件即可。

这种配置对于应用程序各组件是透明的 —— 应用程序不需要做特别的编程,即可使用placeholders。

缺点

并非所有框架都支持这种技术,支持该技术的框架各有不同的用法。

例如:Spring和Log4j都支持placeholder替换,然则它们的做法是完全不同的。

Spring通过PropertyPlaceholderConfigurer类来配置,

而Log4j则需要在DomConfigurator中把参数传进去。

 

编译时替换

Maven Filtering机制

Maven提供了一种过滤机制,可以在资源文件被复制到目标目录的同时,替换其中的placeholders。

5.过滤资源文件

在资源中使用maven里定义的变量,并对所有directory目录下的文件激活资源过滤。

<build>
<!-- 从外部引入过滤文件,没有就使用<properties>里定义的变量过滤 –>
<filters>
<filter>../${props}.properties</filter>   
</filters>
<!—copy到classes目录下–>
<resources>
<!--  处理src/main/java目录里的资源文件*.xml -->
<resource>
    <directory>src/main/java</directory>
    <excludes>
         <exclude>**/*.java</exclude>
    </excludes>
</resource>
<resource>
<targetPath>properties</targetPath>   <!-- classses/properties -->
<directory>src/main/resources</directory>
<!-- 启用过滤 –>
<filtering>true</filtering>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
</build>

 

resources: resource的列表,用于包括所有的资源

targetPath: 指定目标路径,用于放置资源,用于build。默认放在classses目录下。

filtering: 是否替换资源中的属性

directory: 资源所在的位置

includes: 样式,包括那些资源

excludes: 排除的资源

testResources: 测试资源列表

优点

Maven filtering机制和应用所采用的技术、框架完全无关,对应用完全透明,通用性好。

缺点

Maven filtering机制在build时刻永久性改变被过滤的配置文件的内容,build结束以后无法更改。

这将导致一个问题:如果要改变配置文件的参数,必须获取源码并重新build

缺少验证机制。当某个placeholder拼写错误;当properties中的值写错;当某配置文件中新增了一个placeholder,而你的properties文件中没有对应的值时,maven不会提醒你。

而这些错误往往被拖延到应用程序运行时才会被报告出来。

 

AutoConfig机制

AutoConfig是一种类似于Maven Filtering的工具。

这意味着该机制与应用所采用的技术、框架完全无关,对应用完全透明,具有良好的通用性。

同时,AutoConfig与运行时的配置技术并不冲突。它可以和运行时替换的placeholders以及中心配置服务器完美并存,互为补充。

AutoConfig书写placeholder的方法和Maven Filtering机制完全相同。

换言之,Maven Filtering的配置文件模板(前例中的/WEB-INF/**.xml)可以不加修改地用在AutoConfig中。

然而,autoconfig成功克服了Maven Filtering的主要问题。

如何修改配置文件的参数?

Maven Filtering必须获得源码并重新build。

而AutoConfig不需要提取源码,也不需要重新build,就可以改变目标文件中所有配置文件中placeholders的值。

 

如何确保placeholder替换的正确性?

Maven Filtering不能验证placeholder值的缺失和错误;

但AutoConfig可以对placeholder及其值进行检查。

 

开发者

定义应用所需要的properties,及其限定条件;

提供包含placeholders的配置文件模板。

部署者

根据所定义的properties,提供符合限定条件的属性值。

调用AutoConfig来生成目标配置文件。

 

开发者

开发者定义了一个property:petstore.upload_dir,

限定条件为:“合法的文件系统的目录名”。

部署者

部署者取得petstore的二进制发布包,通过AutoConfig了解到应用需要一个名为petstore.upload_dir目录名。

部署者便指定一个目录给petstore,该目录名的具体值可能因不同的系统而异。

AutoConfig会检验该值是否符合限定条件(是否为合法目录名),如果检验通过,就生成配置文件,并将其中的${petstore.upload_dir}替换成该目录名。

 

分享二进制目标文件(重要)

假如project A二进制包中有一些配置文件中的placeholders需要被替换,如果使用Maven Filtering机制,就会出现问题。

因为Maven Filtering只能在project A被build时替换其中的placeholders,一旦project A被发布到repository中,team B的人将无法修改任何project A中的配置参数。

除非team B的人取得project A的源码,并重新build。这将带来很大的负担。

AutoConfig解决了这个问题。

因为当team B的人从maven repository中取得project A的二进制包时,仍然有机会修改其配置文件里的placeholders。

Team B的人甚至不需要了解project A里配置文件的任何细节,AutoConfig会自动发现所有的properties定义,并提示编辑。

 

部署二进制目标文件

部署者也从中受益。因为部署者不再需要亲手去build源代码,而是从maven repository中取得二进制目标文件即可。

 

AutoConfig特性列表

为了满足前面所说的目的,我们将AutoConfig设计成下面的样子:

两种用法

可独立使用(支持Windows和Unix-like平台),也可以作为maven插件来使用

 

autoconfig优点

目标文件而不是源文件进行配置

1、可对同一个目标文件反复配置。

2、配置时不依赖于项目源文件。

3、支持嵌套包文件,例如:ear包含war,war又包含jar。

4、高性能,特别对于嵌套的包文件。

验证和编辑properties

1、自动发现保存于war包、jar包、ear包中的properties定义。

2、验证properties的正确性。

3、交互式编辑properties。

4、当配置文件中出现未定义的placeholders时,提示报错。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics