如何让 maven-assembly-plugin 遵守 pom.xml 中定义的排除项?

How to have maven-assembly-plugin respect the exclusions defined in pom.xml?

TL;DR

当某些(特定的)传递依赖项被 排除在 POM 文件中 程序集描述符被设置为获取所有依赖项时 排除的依赖项将包含在程序集中我怎样才能避免这种情况?

一些背景知识

有些依赖项可能很难处理,因为它们的 groupIds 和 artifactIds 几乎在每个版本(在我的例子中是 bouncycastle)都会改变。

我正在检索几个版本的 bouncycastle(138、1.38、1.45 和 1.50)。我的目的是消除除 1.50 以外的所有版本。准确地说,我有一个依赖项(我们称之为 some.perfectly.done:job)导入 1.50,另一个依赖项(how.many.castles:do-you-need)导入所有其他项。它们是公司依赖项,因此给您真实的 groupId:artifactId 不会帮助您进行测试。

pom.xml

我的依赖声明如下:

<dependency>
    <groupId>some.perfectly.done</groupId>
    <artifactId>job</artifactId>
</dependency>
<dependency>
    <groupId>how.many.castles</groupId>
    <artifactId>do-you-need</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.bouncycastle</groupId>
            <artifactId>*</artifactId>
        </exclusion>
        <exclusion>
            <groupId>bouncycastle</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

assembly.xml

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
    <id>bin</id>
    <formats>
        <format>zip</format>
    </formats>

    <!-- Adds dependencies to zip package under lib directory -->
    <dependencySets>
        <dependencySet>
            <useProjectArtifact>false</useProjectArtifact>
            <useTransitiveFiltering>true</useTransitiveFiltering>
            <outputDirectory>lib</outputDirectory>
                        <outputFileNameMapping>${artifact.groupId}.${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
            <unpack>false</unpack>
        </dependencySet>
    </dependencySets>
    <!-- ... -->
</assembly>

我得到什么

$ ls *bouncycastle*
bouncycastle.bcmail-jdk14-138.jar       org.bouncycastle.bcmail-jdk15on-1.50.jar  org.bouncycastle.bcprov-jdk15-1.45.jar
bouncycastle.bcprov-jdk14-138.jar       org.bouncycastle.bcpkix-jdk15on-1.50.jar  org.bouncycastle.bcprov-jdk15on-1.50.jar
org.bouncycastle.bcmail-jdk14-1.38.jar  org.bouncycastle.bcprov-jdk14-1.38.jar    org.bouncycastle.bctsp-jdk14-1.38.jar

我期望(和需要)的东西

$ ls *bouncycastle*
org.bouncycastle.bcmail-jdk15on-1.50.jar  org.bouncycastle.bcpkix-jdk15on-1.50.jar  org.bouncycastle.bcprov-jdk15on-1.50.jar

一些可能的线索可以建立在

此处答案的真正价值在于找到 真实通用 解决方案。我不想解决 我的 案例,我想为所有有类似案例的人找到解决方案。

因此,我想避免一些可行但确实与特定情况相关并且通常需要将 POM 的逻辑复制到程序集描述符中的解决方案。

但是,如果找不到更好的方法,这些线索可能会有所帮助。

重现程序集描述符中的排除模式

很明显。但在我自己的例子中,除了巧妙地使用 includes/excludes 之外,这是非常不切实际的。这不是一个实用的解决方案。

制作几个依赖集

请注意,我知道 this question has already been asked,但对我的情况来说,唯一的答案尝试并不令人满意:

If you have such thing you need to define two dependencySet entries one which include the logback [with useTransitiveDependencies=false] and other.

(根据khmarbaise

使用maven-dependency-plugin

the same question as above, an approach which I might use if no question is asked has been proposed: first use dependency:copy-dependencies 上将我的正确依赖项复制到一个临时目录,然后 assemble 从该目录压缩我的文件。

作为一种解决方法,这可能是最有效的解决方案,因为它是通用的并且不会在程序集描述符中复制 POM 的逻辑,尽管这会使构建时间更长。

附带问题:为什么?

为什么 maven-assembly-plugin 会这样?我在文档中没有找到对此的任何引用。这是期望的行为,还是 (known/unknown) 错误?

使用maven-dependency-plugin

虽然这不是我正在寻找的最终解决方案,但这可能会帮助处于紧急情况的人。

pom.xml

在您的 POM 中,定义以下内容 属性(根据您的喜好调整路径):

<properties>
    <!-- ... -->
    <assembly.lib.directory>${project.build.directory}/lib</assembly.lib.directory>
    <!-- ... -->
</properties>

<build/>部分:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${assembly.lib.directory}</outputDirectory>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                        <prependGroupId>true</prependGroupId>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <descriptors>
                    <descriptor>src/main/assembly/assembly.xml</descriptor>
                </descriptors>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

assembly.xml

想法是将 dependencySet 替换为 fileSet:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
    <id>bin</id>
    <formats>
        <format>zip</format>
    </formats>

    <!-- Adds dependencies to zip package under lib directory -->
    <fileSets>
        <fileSet>
            <directory>${assembly.lib.directory}</directory>
            <outputDirectory>lib</outputDirectory>
        </fileSet>

        <!-- ... -->
    </fileSets>
</assembly>

编辑:作为highlighted by user716401,最好在prepare-package阶段执行dependencies:copy-dependencies以确保它在assembly:single.

之前运行

我在 spring maven 项目中遇到了同样的问题。查看 pom.xml 文件,我有以下两个 bouncycastle 依赖项。

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.50</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk15on</artifactId>
    <version>1.50</version>
</dependency>

我能够安全地删除 bcprov-jdk15on 依赖块,因为在后续构建成功后似乎没有任何东西依赖它,但是,问题仍然存在。因此,我 运行 在将 pom.xml 文件中的依赖插件版本从 2.6 更新为 2.10 后,以下 maven 命令不起作用。

mvn dependency:tree -Dverbose -Dincludes=bouncycastle

这给出了输出:

[INFO] ------------------------------------------------------------------------
[INFO] Building dhtexasAdmin 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.10:tree (default-cli) @ dhtexasAdmin ---
[WARNING] Using Maven 2 dependency tree to get verbose output, 
[INFO] com.dhtexasadmin:dhtexasAdmin:war:1.0
[INFO] \- org.xhtmlrenderer:core-renderer:jar:R8pre2:compile
[INFO]    \- com.lowagie:itext:jar:2.1.0:compile
[INFO]       +- bouncycastle:bcmail-jdk14:jar:136:compile
[INFO]       \- bouncycastle:bcprov-jdk14:jar:136:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.324 s
[INFO] Finished at: 2017-04-21T16:58:52+01:00
[INFO] Final Memory: 16M/39M
[INFO] ------------------------------------------------------------------------

所以我必须按照示例 Maven Dependency Exclusions

在 xhtmlrenderer 部分添加 bcprov-jdk14 排除项,如下所示
<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>core-renderer</artifactId>
    <version>R8pre2</version>
    <exclusions>
        <exclusion>
            <artifactId>bcprov-jdk14</artifactId>
            <groupId>bouncycastle</groupId>
        </exclusion>
    </exclusions>
</dependency>

之后 mvn clean 然后 mvn package 就成功了。

编辑

maven-assembly-plugin have been released Jan 01, 2019 的版本 3.1.1。它解决了我在下面的回答中提到的 JIRA 问题(保留历史或无法升级插件的用户)。在这个版本中,maven-assembly-plugin 现在在依赖项排除中支持通配符。只需升级插件即可。

maven-assembly-plugin 版本 <= 3.1.0

的答案

Maven 程序集插件(版本 <= 3.1.0)似乎不支持使用通配符排除(*),请参阅 MASSEMBLY-762, MASSEMBLY-861 or MASSEMBLY-675. From the last JIRA issue, the problem will be solved in version 3.1.1 of the plugin (see commit) . 在撰写本文时,3.1.1 版本尚未发布:3.1.0 是最新版本

希望版本 <= 3.1.0 可以解决问题。

为此,只需声明正确的排除工件而不是 *,它就可以正常工作。列出所有排除的依赖项可能会很痛苦,但至少我认为这是一个比公认的解决方案更好的解决方案(对 Maven 阶段的调整较少),尤其是在具有交叉依赖项的多模块项目上(我的案例)。此外,通过这样做,您可以更好地控制依赖关系。

希望对您有所帮助,等待 3.1.1 版本! :)