如果两个或多个元素(例如,文件、文件集)为同一文件选择不同的源进行归档,则只有一个源文件将被归档。
根据程序集插件的 2.5.2 版本,将文件添加到存档“获胜”的第一阶段。过滤仅基于存档中的名称完成,因此可以在不同的输出名称下添加相同的源文件。阶段的顺序如下:1) FileItem 2) FileSets 3) ModuleSet 4) DependedencySet 和 5) Repository 元素。
相同类型的元素将按照它们在描述符中出现的顺序进行处理。如果您需要“覆盖”前一组包含的文件,唯一的方法是将该文件从前一组中排除。
请注意,此行为在早期版本的程序集插件中略有不同。
当使用dependencySet或moduleSet时,<includes/>和<excludes/>部分实际上适用于工件,而不是文件名。这可能是一件好事,因为您不必知道工件在本地存储库中的文件名。但是,为要包含或排除的每个工件显式指定完整的工件 ID(由 groupId、artifactId、版本、类型和分类器组成)可能会导致非常冗长的描述符。从 2.2 版开始,程序集插件通过使用通配符模式解决了显式工件识别的笨拙问题。
在指定工件匹配模式时,应应用以下简单规则:
在本例中,我们将配置一个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>
在这个例子中,我们正在处理一个事实,即项目源通常使用 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>
对于大多数用例,避免从源代码控制系统添加元数据文件很重要,例如 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模式的未来扩展留出空间,包括有朝一日更改默认模式语法的选项。
在这个例子中,我们想要生成一个 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目录结构中的任何目标目录都将保留在程序集中。
有时,您希望在创建程序集时构建一组健全性检查,以确保进入程序集工件的内容是您想要的。一种方法是在您的dependencySets、moduleSets和fileSets上启用useStrictFiltering。
useStrictFiltering是一个标志,它告诉程序集插件跟踪每个包含/排除模式,以确保在创建程序集期间使用它。这样,如果程序集描述符作者打算出现特定文件或工件,他可以向描述符添加包含/排除模式以确保文件/工件存在,然后设置useStrictFiltering标志。如果在程序集创建期间该模式未用于匹配至少一个文件,则构建将失败,并且用户将收到一条消息,通知他未使用的模式。
在此示例中,我们希望确保我们的项目 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-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>