10.3. 通用生命周期目标

很多打包类型的生命周期有类似的目标。如果你看一下绑定到WARJAR生命周期的目标,你会发现它们只有在package阶段有区别。WAR生命周期的package阶段调用了war:war,而JAR生命周期的package阶段调用了jar:jar。大部分你将要接触的生命周期共享一些通用生命周期目标,用来管理资源,运行测试,以及编译源代码。本节,我们会详细讨论这些通用的生命周期目标。

10.3.1. Process Resources

大部分生命周期将resources:resources目标绑定到process-resources阶段。process-resources阶段处理资源并将资源复制到输出目录。如果你没有自己自定义超级POM中的默认目录位置,Maven就会将/data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh/src/main/resources中的文件复制到/data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh/target/classes,或者是由/data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh/target/classes定义的目录。除了复制资源文件至输出目录,Maven同时也会在资源上应用过滤器,能让你替换资源文件中的一些符号。就像在POM中我们通过MavenProject: org.sonatype.mavenbook:content-zh:0.5 @ /data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh/pom.xml标记引用变量一样,你也可以使用同样的语法在你项目的资源文件中引用变量。与profile联系起来,这样的特性就能用来生成针对不同部署平台的构件。当我们需要为同一个项目的开发,测试,staging,以及产品平台环境生成输出的时候,该特性就十分有用。要了解更多的关于构建profile的信息,查看Chapter 11, 构建Profile

为了阐述资源过滤,假设你有个带有XML文件src/main/resources/META-INF/service.xml的项目。你想要提取出一些配置变量至一个属性文件。换句话说,你可能想要为你的数据库引用JDBC URL,用户名和密码,并且你不想将这些值直接放到service.xml文件里,而是想要使用一个属性文件来存储你程序中的所有配置点。这么做能让你将所有配置信息固定到单独的一个属性文件中,当你需要面对一个新的部署环境的时候,就很容易更改配置的值。首先,看一下src/main/resources/META-INF/service.xml的内容。

Example 10.4. 在项目资源中使用属性

<service>
  <!-- This URL was set by project version 0.5 -->
  <url>${jdbc.url}</url>
  <user>${jdbc.username}</user>
  <password>${jdbc.password}</password>
</service>


XML文件使用你在POM中用到的同样的属性引用语法,第一个引用的变量是project,它同时也是POM中的隐式变量。project变量提供了对POM信息的访问。接下来的三个变量引用是,jdbc.urljdbc.usernamejdbc.password。这些自定义的变量在一个属性文件src/main/filters/default.properties中定义。

Example 10.5. src/main/filters中的default.properties

jdbc.url=jdbc:hsqldb:mem:mydb
jdbc.username=sa
jdbc.password=

要配置使用该default.properties文件的资源过滤,我们需要在这个项目的POM中指定两样东西:构建配置的filters元素中的属性文件列表,以及一个标记告诉Maven资源目录需要过滤。默认的Maven行为会跳过过滤,只是将资源复制到输出目录;你需要显式的配置资源过滤,否则Maven就会置之不理。这种Maven资源过滤的默认行为是为了确保不让Maven替换掉一些你不想替换的MavenProject: org.sonatype.mavenbook:content-zh:0.5 @ /data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh/pom.xml引用。

Example 10.6. 过滤资源 (替换属性)

<build>
  <filters>
    <filter>src/main/filters/default.properties</filter>
  </filters>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>
</build>


正如Maven中所有目录一样,资源目录并非一定要在src/main/resources。这只是定义在超级POM中的默认值。你应该也注意到你不需要将你所有的资源合并到一个单独的目录中。你可以将资源分离至src/main目录下的独立的目录中。假设你有个项目包含了数百个XML文档和数百个图片。你可能希望创建两个目录src/main/xmlsrc/main/images来存储这些内容,而不是将它们混合在src/main/resources目录中。为了添加资源目录列表,你需要在你的构建配置中加入如下的resource元素:

Example 10.7. 配置额外的资源目录

<build>
  ...
  <resources>
    <resource>
      <directory>src/main/resources</directory>
    </resource>
    <resource>
      <directory>src/main/xml</directory>
    </resource>
    <resource>
      <directory>src/main/images</directory>
    </resource>
  </resources>
  ...
</build>

当你构建一个项目用来生成控制台程序或者命令行工具的时候,你通常发现自己正编写一个shell脚本,需要引用构建生成的JAR。当你使用assembly插件为一个应用程序生成如ZIPTAR的分发包的时候,你可能会将所有的脚本放到如src/main/command的目录下。在下面的POM资源配置中,你会看到我们如何使用资源过滤器和一个对项目变量的引用,生成JAR的最终名称。要了解更多的关于Maven Assembly插件的信息,参考Chapter 12, Maven套件

Example 10.8. 过滤脚本资源

<build>
  <groupId>org.sonatype.mavenbook</groupId>
  <artifactId>simple-cmd</artifactId>
  <version>2.3.1</version>
  ...
  <resources>
    <resource>
      <filtering>true</filtering>
      <directory>/data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh/src/main/command</directory>
      <includes>
        <include>run.bat</include>
        <include>run.sh</include>
      </includes>
      <targetPath>/data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh</targetPath>
    </resource>
    <resource>
      <directory>/data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh/src/main/resources</directory>
    </resource>
  </resources>
  ...
</build>


如果你在该项目中运行mvn process-resources,最后你会在/data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh中得到两个文件,run.shrun.bat,我们在resource元素中挑选出这两个文件,配置过滤器,然后设置targetPath/data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh。在第二个resource元素中,我们配置了默认资源路径,使其在不做过滤的情况下被复制到默认输出目录。Example 10.8, “过滤脚本资源”告诉你如何声明两个资源目录,如何给它们提供不同的过滤配置和目标目录配置。Example 10.8, “过滤脚本资源”项目的src/main/command目录下包含了一个含有如下内容的run.bat文件。

@echo off
java -jar book.jar %*

在运行了mvn process-resources之后,目录/data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh下会有一个含有如下内容的名为run.bat的文件:

@echo off
java -jar simple-cmd-2.3.1.jar %*

在带有很多不同种类资源的复杂的项目中,我们会发现将资源分离到多个目录下十分有利,原因之一就是我们可以为特定的资源子集自定义过滤器。针对不同的过滤需求,除了将资源存储到不同的目录下,我们还可以使用更复杂的一组包含/排除模式来匹配那些符合模式的资源文件。