高级装配描述符主题

所有包含排除模式的快速说明

excludes优先于include

存档文件分辨率

如果两个或多个元素(例如,文件、文件集)为同一文件选择不同的源进行归档,则只有一个源文件将被归档。

根据程序集插件的 2.5.2 版本,将文件添加到存档“获胜”的第一阶段。过滤仅基于存档中的名称完成,因此可以在不同的输出名称下添加相同的源文件。阶段的顺序如下:1) FileItem 2) FileSets 3) ModuleSet 4) DependedencySet 和 5) Repository 元素。

相同类型的元素将按照它们在描述符中出现的顺序进行处理。如果您需要“覆盖”前一组包含的文件,唯一的方法是将该文件从前一组中排除。

请注意,此行为在早期版本的程序集插件中略有不同。

包含排除中的高级工件匹配

当使用dependencySetmoduleSet时,<includes/><excludes/>部分实际上适用于工件,而不是文件名。这可能是一件好事,因为您不必知道工件在本地存储库中的文件名。但是,为要包含或排除的每个工件显式指定完整的工件 ID(由 groupId、artifactId、版本、类型和分类器组成)可能会导致非常冗长的描述符。从 2.2 版开始,程序集插件通过使用通配符模式解决了显式工件识别的笨拙问题。

在指定工件匹配模式时,应应用以下简单规则:

  1. 工件由一组标识符字符串匹配。在以下字符串中,type默认为'jar' ,如果为 null,则省略 分类器。
    • groupId:artifactId:type:classifier ( artifact.getDependencyConflictId() )
    • groupId:artifactId ( ArtifactUtils.versionlessKey(artifact) )
    • groupId:artifactId:type:classifier:version ( artifact.getId() )
  2. 包含/排除模式中的任何'*'字符都将导致模式被拆分,并且使用String.indexOf(..)在上述三个工件标识符中匹配子模式。
  3. 当包含/排除模式中不存在“*”时,仅当整个模式等于上述三个工件标识符之一时,该模式才会匹配,使用String.equals(..)方法。
  4. 如果您在上面错过了它,工件识别字段在匹配的字符串中用冒号 ( ':' ) 分隔。因此,匹配任何类型为“war”的工件的通配符模式可能被指定为*:war

示例:包含所有类型为“war”的依赖项

在本例中,我们将配置一个dependencySet,使其仅包含那些战争依赖项。

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
  [...]
  <dependencySets>
    <dependencySet>
      <includes>
        <include>*:war</include>
      </includes>
    </dependencySet>
  </dependencySets>
  [...]
</assembly>
明白了!

在上面的示例中,任何碰巧有分类器的战争工件(不确定为什么会发生这种特殊情况,但可能)将被跳过。如果您真的想小心捕捉项目中的所有战争工件,您可能需要使用以下模式:

*:war:*

示例:排除所有 source-jar 依赖项。

在这个例子中,我们正在处理一个事实,即项目源通常使用 jar 文件分发,除了普通的二进制文件。我们想从二进制 jar中过滤掉任何 source-jar 文件(它们将用源分类器标记)。

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
  [...]
  <dependencySets>
    <dependencySet>
      <includes>
        <include>*:jar:*</include>
      </includes>
      <excludes>
        <exclude>*:sources</exclude>
      </excludes>
    </dependencySet>
  </dependencySets>
  [...]
</assembly>

在 FileSet 中包含 Subversion 元数据目录

对于大多数用例,避免从源代码控制系统添加元数据文件很重要,例如 Subversion 的.svn目录。这样的元数据可以极大地增加生成的程序集的大小。默认情况下,程序集插件将从描述符中指定的fileSet中排除大多数常见源代码控制系统的元数据文件。

另一方面,如果你包含 Subversion 元数据目录怎么办?从版本 2.2 开始,程序集插件在所有fileSet元素上提供了useDefaultExcludes选项,以适应此用例。

示例:为开发人员快速入门包捆绑项目源

在此示例中,让我们检查如果您在源代码管理中有一个大型项目会发生什么。在项目生命周期的早期阶段,该项目包含大量自添加之日起未更改的相当大的文件。您希望让潜在的开发人员能够快速入门,而无需先检查数百个 10 兆字节的文件。

与许多存档格式结合的压缩可以在这里提供优势。如果我们创建一个项目程序集,包括 Subversion 元数据目录,开发人员应该能够下载程序集工件并展开它,然后只需键入svn up

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
  [...]
  <fileSets>
    <fileSet>
      <useDefaultExcludes>false</useDefaultExcludes>
      <excludes>
        <exclude>**/target/**</exclude>
      </excludes>
    </fileSet>
  </fileSets>
  [...]
</assembly>

注意:您会注意到我们排除了所有目标目录;这些是“计算”和其他临时数据的一种形式,通常不应包含在存档中,除非您的目标是创建项目二进制文件或类似文件。

使用正则表达式排除文件

有时,您可能会发现需要为fileSet指定极其细粒度的包含或排除模式。在这些情况下,您可以选择使用%regex[...]语法以正则表达式的形式指定模式。

注意:为了完整起见,默认模式类型 - Ant 样式模式 - 也可以使用新的%ant[...]语法指定。这将为fileSet模式的未来扩展留出空间,包括有朝一日更改默认模式语法的选项。

示例:在src目录中包含名为target的目录

在这个例子中,我们想要生成一个 Maven 项目层次结构的可构建源分布。显然,每个项目的目标目录都是构建过程的临时工作空间,所以我们要排除这些目录。但是,如果一个或多个项目还在src目录结构中包含一个名为target的子目录(可能是 Java 包名称的一部分),我们希望确保该目录中的文件包含在程序集中。

<assembly>
  [...]
  <fileSets>
    <fileSet>
      <directory>E:\java-workspace\apache-maven-plugins\plugins\maven-assembly-plugin\target\checkout</directory>
      <outputDirectory></outputDirectory>
      <excludes>
        <exclude>%regex[(?!.*src/).*target.*]</exclude>
      </excludes>
    </fileSet>
    [...]
  </fileSets>
  [...]
</assembly>

上面的fileSet使用了一个有点晦涩的正则表达式特性,称为负前瞻,这意味着我们的排除模式将只匹配包含单词target包含src的路径。实际上,src目录结构中的任何目标目录都将保留在程序集中。

使用严格过滤来捕捉过时的模式或不正确的构建

有时,您希望在创建程序集时构建一组健全性检查,以确保进入程序集工件的内容是您想要的。一种方法是在您的dependencySetsmoduleSetsfileSets上启用useStrictFiltering

useStrictFiltering是一个标志,它告诉程序集插件跟踪每个包含/排除模式,以确保在创建程序集期间使用它。这样,如果程序集描述符作者打算出现特定文件或工件,他可以向描述符添加包含/排除模式以确保文件/工件存在,然后设置useStrictFiltering标志。如果在程序集创建期间该模式未用于匹配至少一个文件,则构建将失败,并且用户将收到一条消息,通知他未使用的模式。

示例:确保 LICENSE.txt 文件包含在 jar 中

在此示例中,我们希望确保我们的项目 jar 包含项目的开源许可语言,以符合我们软件基金会的政策。

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
  [...]
  <fileSets>
    <fileSet>
      <useStrictFiltering>true</useStrictFiltering>
      <outputDirectory>META-INF</outputDirectory>
      <includes>
        <include>LICENSE.txt</include>
      </includes>
    </fileSet>
    [...]
  </fileSets>
  [...]
</assembly>

如果开发人员无意中从项目目录中删除了 LICENSE.txt,则程序集插件应拒绝构建此程序集。

使用替代程序集基目录

在许多情况下,程序集应将所有文件安排在一个程序集基目录下。这样,展开程序集的用户会将所有内容收集在一个漂亮、整洁的目录结构中,而不是分散在当前工作目录中。这是使用includeBaseDirectory标志实现的,并且该标志默认设置为true,这将导致项目的artifactId-version被用作程序集基目录。

但是,在某些特殊情况下,您可能希望对程序集的根目录使用不同的目录名称。从 2.2 版本的程序集插件开始,此用例使用程序集描述符的baseDirectory元素来处理。使用此元素,您可以使用 POM 表达式和静态字符串来指定程序集根目录的名称。

示例:Maven 程序集的 Eclipse 风格的不变目录名称

在本例中,让我们探讨如果我们希望 Maven 使用 Eclipse 方法来命名其分发程序集中的根目录会发生什么。这样,您无需扩展发行版以查找新的maven-2.0.4目录,而是找到一个maven目录。此外,考虑到分发程序集当前是从maven-core项目构建的,这意味着我们不应将artifactId用作程序集根目录的一部分。

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
  [...]
  <baseDirectory>maven</baseDirectory>
  [...]
</assembly>

现在,假设分发程序集是在顶级maven项目中创建的。现在,我们可以使用artifactId并且可能应该使用,只是为了尽量减少对这些文件的维护。

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
  [...]
  <baseDirectory>${artifactId}</baseDirectory>
  [...]
</assembly>

高级模块设置主题

程序集描述符中最复杂的部分之一是moduleSets部分。事实上,这部分已经进行了很多改进,我们认为它值得拥有自己的“高级主题”页面。