为什么maven-war-plugin的行为与标准的maven依赖解析机制不同

时间:2014-12-03 20:50:52

标签: java eclipse maven

maven-war-plugin的行为与标准的maven依赖解析机制有什么不同? 我有一个具有依赖性的war maven项目:

    <dependency>
        <groupId>GroupA</groupId>
        <artifactId>DependencyA</artifactId>
        <exclusions>
            <exclusion>
                <groupId>GroupB</groupId>
                <artifactId>DependencyB</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

正确排除了上述依赖关系,我可以在依赖关系层次结构视图上进行验证。 当我用maven构建war时,它包含了WEB-INF/lib目录中的DependencyB,因此我必须明确定义使用maven-war-plugin将其排除,如下所示:

        <plugin>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <warSourceDirectory>src/main/webapp</warSourceDirectory>
                <packagingExcludes>
                    WEB-INF/lib/dependencyB.jar,
                </packagingExcludes>
            </configuration>
        </plugin>

我必须做以上原因导致我的项目出现版本之间的冲突。 为什么会这样? 还有另一种方法可以达到这个目的吗?


更新

所以我创建了一个测试用例,只是为了向您展示我的意思,如果我之前不够清楚的话。 相应的pom如下:

ArtifactA:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>GroupA</groupId>
<artifactId>ArtifactA</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>ArtifactA Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>GroupB</groupId>
        <artifactId>ArtifactB</artifactId>
        <type>war</type>
        <version>0.0.1-SNAPSHOT</version>
        <exclusions>
            <exclusion>
                <groupId>GroupC</groupId>
                <artifactId>ArtifactC</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>


<build>
    <finalName>ArtifactA</finalName>
</build>

ArtifactB

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>GroupB</groupId>
<artifactId>ArtifactB</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>ArtifactB Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>GroupC</groupId>
        <artifactId>ArtifactC</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>
<build>
    <finalName>ArtifactB</finalName>
</build>

ArtifactC

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>GroupC</groupId>
<artifactId>ArtifactC</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>ArtifatcC</name>
<url>http://maven.apache.org</url>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>

在Eclipse中的依赖项Hierarchy中,我没有看到依赖项ArtifactC。 enter image description here

在构建ArtifactA并解压缩.war时,我得到: enter image description here

正如您所见,传递依赖包含在WEB-INF / lib的.war中。 我希望现在更清楚了。

要添加的其他一些细节:

  1. 我从eclipse打电话给maven
  2. maven-war-plugin版本2.1.1,也测试了2.5
  3. Eclipse中嵌入的Maven版本3.0.4

2 个答案:

答案 0 :(得分:2)

问题不在于war插件以不同方式处理依赖项排除,而是它特别处理<type>war</type>的依赖项。它创建了一个war overlay,这意味着它需要战争的全部内容,并将项目的Web资源放在首位。 war依赖实际上没有传递依赖,它已经包含了所有jar文件。

如果您真的有意使用战争叠加,那么使用packagingExcludes是正确的解决方案。如果您想要依赖工件B中的类,那么您应该修改pom,以便创建一个单独的工件(使用attachClasses configuration)并依赖于此classes工件。然后,排除传递依赖项应该与任何其他jar依赖项一样。

答案 1 :(得分:0)

我也注意到<exclusions>的奇怪行为。我最好的建议是把它放在战争项目(项目A)中。

<dependency>
    <groupId>GroupC</groupId>
    <artifactId>ArtifactC</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <scope>provided</scope>
</dependency>

注意范围provided

我必须经常这样做以进行公共记录,因为某些东西似乎总是会导致它被包含在内,而且它只是a $$中的一个痛点,可以在任何地方标记排除。

另一个选择是在项目B中执行此操作:

<dependency>
    <groupId>GroupC</groupId>
    <artifactId>ArtifactC</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <optional>true</optional>
</dependency>

然后在实际需要的地方明确添加ArtifactC和ArtifactB依赖项(即在其他地方部署B)。

注意optional

就像我在评论中所说,我认为依靠<exclusions>不是一个好主意。它通常意味着某些东西被打破。如果是造成它的人,那就特别糟糕了。