使用Maven汇编插件管理多模块依赖关系



我使用Maven汇编插件为我的多模块项目创建一个程序集。这个多模块项目构建了两个独立的应用程序,每个应用程序都有一组独立的依赖项。我制作了一个自定义的汇编描述符,它用模块构建及其各自的依赖关系汇编两个目录(每个应用程序)。它做得很好,但有一点——它将两个模块的依赖关系放在彼此的程序集中。

以下是我的项目的简化版本,具有完全相同的行为。

考虑一个由两个模块和一个组装模块组成的项目:

APP
  module1
  module2
  assembly

我添加了纯粹用于演示的依赖项:

com.test.app:module1:jar:1.0
- commons-cli:commons-cli:jar:1.2:compile
com.test.app:module2:jar:1.0
- commons-daemon:commons-daemon:jar:1.0.8:compile

这是父POM:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test</groupId>
  <artifactId>app</artifactId>
  <version>1.0</version>
  <packaging>pom</packaging>
  <modules>
    <module>module1</module>
    <module>module2</module>
    <module>assembly</module>
  </modules>
</project>

模块1 POM:

<project>
  <parent>
    <groupId>com.test</groupId>
    <artifactId>app</artifactId>
    <version>1.0</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test.app</groupId>
  <artifactId>module1</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>
  <dependencies>
    <dependency>
      <groupId>commons-cli</groupId>
      <artifactId>commons-cli</artifactId>
      <version>1.2</version>
    </dependency>
  </dependencies>
</project>

模块2 POM:

<project>
  <parent>
    <groupId>com.test</groupId>
    <artifactId>app</artifactId>
    <version>1.0</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test.app</groupId>
  <artifactId>module2</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>
  <dependencies>
    <dependency>
      <groupId>commons-daemon</groupId>
      <artifactId>commons-daemon</artifactId>
      <version>1.0.8</version>
    </dependency>
  </dependencies>
</project>

组装POM:

<project>
  <parent>
    <groupId>com.test</groupId>
    <artifactId>app</artifactId>
    <version>1.0</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test.app</groupId>
  <artifactId>assembly</artifactId>
  <version>1.0</version>
  <packaging>pom</packaging>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.2.2</version>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <appendAssemblyId>false</appendAssemblyId>
          <descriptors>
            <descriptor>src/main/assembly/descriptor.xml</descriptor>
          </descriptors>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

最后,组装描述符:

<assembly>
  <id>distribution</id>
  <includeBaseDirectory>false</includeBaseDirectory>
  <formats>
    <format>dir</format>
  </formats>
  <moduleSets>
    <moduleSet>
      <useAllReactorProjects>true</useAllReactorProjects>
      <includes>
        <include>com.test.app:module1:jar</include>
      </includes>
      <binaries>
        <outputDirectory>module1</outputDirectory>
        <unpack>false</unpack>
        <dependencySets>
          <dependencySet>
            <unpack>false</unpack>
          </dependencySet>
        </dependencySets>
      </binaries>
    </moduleSet>
    <moduleSet>
      <useAllReactorProjects>true</useAllReactorProjects>
      <includes>
        <include>com.test.app:module2:jar</include>
      </includes>
      <binaries>
        <outputDirectory>module2</outputDirectory>
        <unpack>false</unpack>
        <dependencySets>
          <dependencySet>
            <unpack>false</unpack>
          </dependencySet>
        </dependencySets>
      </binaries>
    </moduleSet>
  </moduleSets>
</assembly>

正如您所看到的,程序集是绑定到包阶段的。所以,当我执行时

mvn package

从父目录,我有以下程序集

module1/
  commons-cli-1.2.jar
  commons-daemon-1.0.8.jar
  module1-1.0.jar
module2/
  commons-cli-1.2.jar
  commons-daemon-1.0.8.jar
  module2-1.0.jar

基本上,这里的问题是module1不依赖于commons守护进程,但汇编插件包含了依赖关系。类似地,使用module2和commons-cli。

有人能解释一下为什么汇编插件会这样做吗?

什么是解决方案?

在多模块项目中使用汇编插件时,我一直有类似的经历,但最终结果并不是我所期望的。我希望其他人能提供一个更准确的答案,解释为什么会发生这种情况,以及如何最好地同时使用这两个概念。

也就是说,一个可能的解决方案是让模块1和模块2生成它们自己的汇编工件,这些工件包含它们各自的jar和依赖项。然后,您可以修改程序集子模块pom文件,使其依赖于从其同级模块生成的分发工件,然后将这些工件解压缩到新程序集中。

在Module1和Module2的pom文件中,您可以像处理汇编子模块一样,将汇编插件配置添加到包阶段。

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.2.2</version>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <descriptors>
            <descriptor>src/main/assembly/descriptor.xml</descriptor>
          </descriptors>
        </configuration>
      </plugin>
    </plugins>
  </build>

Module1将有一个类似的src/main/assembly/descriptor.xml

<assembly>
  <id>distribution</id>
  <includeBaseDirectory>false</includeBaseDirectory>
  <formats>
    <format>zip</format>
  </formats>
  <dependencySets>
    <dependencySet>
      <outputDirectory>module1</outputDirectory>
      <unpack>false</unpack>
    </dependencySet>
  </dependencySets>
</assembly>

Module2将具有类似的src/main/assembly/descriptor.xml

<assembly>
  <id>distribution</id>
  <includeBaseDirectory>false</includeBaseDirectory>
  <formats>
    <format>zip</format>
  </formats>
  <dependencySets>
    <dependencySet>
      <outputDirectory>module2</outputDirectory>
      <unpack>false</unpack>
    </dependencySet>
  </dependencySets>
</assembly>

然后在assembly/pom.xml中,您将添加模块1和2 zip工件作为依赖项

  <dependencies>
    <dependency>
      <groupId>com.test.app</groupId>
      <artifactId>module1</artifactId>
      <version>1.0</version>
      <type>zip</type>
      <classifier>distribution</classifier>
    </dependency>
    <dependency>
      <groupId>com.test.app</groupId>
      <artifactId>module2</artifactId>
      <version>1.0</version>
      <type>zip</type>
      <classifier>distribution</classifier>
    </dependency>
  </dependencies>

并将assembly/src/main/assembly/descriptor.xml文件修剪为如下

<assembly>
  <id>distribution</id>
  <includeBaseDirectory>false</includeBaseDirectory>
  <formats>
    <format>dir</format>
  </formats>
  <dependencySets>
    <dependencySet>
      <useTransitiveDependencies>false</useTransitiveDependencies>
      <unpack>true</unpack>
    </dependencySet>
  </dependencySets>
</assembly>

正如我所说,这将是一个可能的解决方案,不幸的是,它为您的构建过程添加了大量额外的XML配置。但它是有效的。

最新更新