13.3. 资源过滤

你可以使用Maven来对项目资源进行变量替换。在资源过滤被激活的时候,Maven会扫描资源,寻找由${}包围的Maven属性的引用。一旦它找到这些引用,它就会使用合适的值去替换它们,就像前一节中定义的属性可以在POM中引用一样。当你需要根据目标部署平台使用不同的配置来参数化一个构建的时候,这就非常有用。

通常一个在src/main/resources目录下的.properties文件或者XML文档会包含对外部资源的引用,如需要根据目标部署平台进行不同配置的数据库或网络地址。例如,一个从数据库读取数据的系统有一个XML文档,其包含了数据库的JDBC URL以及安全凭证。如果你在开发和产品环境使用不同的数据库。你可以选择使用一种技术如JNDI将配置信息从应用程序提取出来至应用服务器,或者你可以创建一个知道如何根据目标平台用不同的值替换变量的构建。

使用Maven资源过滤,你可以引用Maven属性,并且使用Maven Profile来为不同的部署环境定义不同的配置。为了展示这个功能,假设你有一个项目,它使用了Spring Framework来配置来自于Commons DBCP项目的BasicDataSource。你的项目可能在src/main/resources中包含一个文件applicationContact.xml,它含有如Example 13.3, “在资源中引用Maven属性”所示的XML

Example 13.3. 在资源中引用Maven属性

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="someDao" class="com.example.SomeDao">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>

你的程序会在运行的时候读取这个文件,而你的构建将会使用定义在你pom.xml中的值替换如jdbc.urljdbc.username这样的属性。默认情况资源过滤是关闭的,那是为了避免非有意的资源过滤。要开启资源过滤,你需要使用POM中build元素下的resources子元素。Example 13.4, “定义变量和激活资源过滤”展示了这样一个POM,它定义了在Example 13.3, “在资源中引用Maven属性”中引用的变量,并且为所有位于src/main/resources下的资源激活了资源过滤。

Example 13.4. 定义变量和激活资源过滤

<project>
  ...
  <properties>
    <jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName>
    <jdbc.url>jdbc:mysql://localhost:3306/development_db</jdbc.url>
    <jdbc.username>dev_user</jdbc.username>
    <jdbc.password>s3cr3tw0rd</jdbc.password>
  </properties>
  ...
  <build>
    <resources>
      <resource>src/main/resources</resource>
      <filtering>true</filtering>
    </resources>
  </build>
  ...
  <profiles>
    <profile>
      <id>production</id>
      <properties>
        <jdbc.driverClassName>oracle.jdbc.driver.OracleDriver</jdbc.driverClassName>
        <jdbc.url>jdbc:oracle:thin:@proddb01:1521:PROD</jdbc.url>
        <jdbc.username>prod_user</jdbc.username>
        <jdbc.password>s00p3rs3cr3t</jdbc.password>
      </properties>
    </profile>  
  </profiles>
</project>

四个变量在properties元素中定义,并且我们为src/main/resources下的资源开启了资源过滤。资源过滤默认是关闭的,为了激活它你必须为项目中的资源显式的设置filteringtrue。默认关闭资源过滤的目的是为了防止构建中偶然发生的非有意的过滤。如果你使用Example 13.3, “在资源中引用Maven属性”中的资源和Example 13.4, “定义变量和激活资源过滤”中的POM构建一个项目,然后列出target/classes下的资源内容,你会看到那里的资源文件已经被过滤。

$ mvn install
...
$ cat target/classes/applicationContext.xml
...
    <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/development_db"/>
        <property name="username" value="dev_user"/>
        <property name="password" value="s3cr3tw0rd"/>
    </bean>
...

Example 13.4, “定义变量和激活资源过滤”中的POM还在profiles/profile元素下定义了一个production profile,它使用适合产品环境中的值覆盖了默认的属性。在这个特别的POM中,数据库连接默认的值是针对于安装在开发者机器上的本地MySQL数据库。而在production profile激活时构建这个项目,Maven会使用不同的驱动类,URL,用户名,和密码,配置系统连接到产品环境的Oracle数据库。如果你使用Example 13.3, “在资源中引用Maven属性”中的资源和Example 13.4, “定义变量和激活资源过滤”中的POM,并激活了production file,然后构建一个项目,最后列出target/classes中的资源内容,你会看到其包含了使用产品环境值过滤的资源。

$ mvn -Pproduction install
...
$ cat target/classes/applicationContext.xml
...
    <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
        <property name="url" value="jdbc:oracle:thin:@proddb01:1521:PROD"/>
        <property name="username" value="prod_user"/>
        <property name="password" value="s00p3rs3cr3t"/>
    </bean>
...