【问题标题】:How to set up maven for two separate projects that depend on the same jar如何为依赖同一个jar的两个独立项目设置maven
【发布时间】:2010-12-10 06:39:44
【问题描述】:

如果在其他地方回答了这个问题,请拍打我并指出正确的方向。

我是 Maven 的新手,我正在努力思考如何在我的项目中使用它。我有两个顶级项目,一个是 Swing 应用程序,另一个是一组 Web 服务。它们都依赖于同一个内部 jar。为此设置 pom 的好方法是什么?

如果 jar 仅由其中一个项目使用,那么看起来我会将其向下移动并使其成为一个模块。但我不想要该 jar 源代码的两个(以及更多)副本。

看起来我可以做到这一点的一种方法是为 Swing 应用程序提供一个主 pom,其中包含 Swing 应用程序和库 jar 作为模块。然后以相同的方式为 Web 应用程序设置另一个主 pom。这有意义吗?有更好的方法吗?

目录结构目前非常简单:

Development/  
----SwingApp/  
----WebServices/  
----CoreLibrary/  

接下来有太多信息和附带问题:

我继承了一个“构建系统”(松散地使用术语),它是 100% Netbeans 自动生成的 ant 脚本。我开始尝试将其放入我非常喜欢的持续集成 TeamCity 中。我在尝试用它构建 WebServices 项目时遇到了严重的问题。据我所知,生成的 ant (build-impl.xml) 中有些东西不能在 CI 环境中被覆盖。将此与日常开发中的一些严重的类路径地狱结合起来,您就会开始明白我为什么要使用 maven。

包含在这个问题中的一个问题是我团队中的开发人员似乎都有一个习惯。现在,Netbeans 中的各种项目都有对“CoreLibrary”项目的项目引用。这意味着当“CoreLibrary”中的源发生更改并且开发人员在顶级应用程序上进行构建时,它还将根据需要构建 CoreLibrary。可以在Maven中模拟吗?这将有助于缓解过渡。到目前为止,我看到 Netbeans (6.7) 并没有在 maven 构建中做到这一点,而且我认为我不能出售(还)在 Netbeans 之外进行日常构建工作。

【问题讨论】:

  • 有没有人幸运地这样做了:chasethedevil.blogspot.com/2007/04/… ../guide-ide-eclipse-site../guide-ide -eclipse-core../guide-ide-eclipse-module1
  • @jcullison 我已经阅读了您发布的链接的帖子和 cmets。显然,我不同意作者和 cmets。我从 2003 年开始使用 Maven,但我不知道人们在说什么。当然,使用 Maven 有一些学习曲线,但是一旦您知道如何使用它,Maven 真的 是一个不错的工具,我绝对不会浪费时间使用它。人们在帖子中提到的大多数事情都是由于缺乏知识恕我直言。
  • 但是您是否曾经在模块中使用过相对 (../project2) 引用?你特别不同意那部分吗?
  • 假设我在库模块中工作,并且我想使用 Swing 应用程序对其进行测试,如果我从 Swing 目录运行“mvn clean install”,则不会重新编译库模块。有没有办法在我构建当前项目时重新编译父项目中的所有依赖项?
  • 答案在接受的答案(绿色复选标记)内,其中显示“mvn -am --projects webServices clean install”。但是,不要在 cmets 中发布问题,请开始您自己的问题。我花了一个月才注意到这一点。

标签: java maven-2 build


【解决方案1】:

在您的 Development 目录中,您将有一个类似于以下内容的 pom:

<project>
    <groupId>yourGroup</groupId>
    <artifactId>project</artifactId>
    <packaging>pom</packaging>
    <modules>
        <module>coreLibrary</module>
        <module>swingApp</module>
        <module>webServices</module>
    </modules>
</project>

是的,我省略了一些其他元素,所以填写完整 pom 所需的其他任何内容。

然后,您的 coreLibrary、swingApp 和 webServices 模块将每个都有一个带有父元素和任何依赖项的 pom,如下所示

<project>
    <parent>
        <groupId>yourGroup</groupId>
        <artifactId>project</artifactId>
        <version>yourVersion</version>
    </parent>
    <artifactId>webServices</artifactId>
    <packaging>war</packaging>
    <version>yourVersion</version>
    <dependencies>
        <dependency>
            <groupId>yourGroup</groupId>
            <artifactId>coreLibrary</artifactId>
            <version>yourVersion</version>
        </dependency>
    </dependencies>
</project>

如果您在根级别构建,那么它将构建所有 3 个模块,或者更好的是,您可以使用 --also-make 选项仅构建 webServices 及其依赖项(在本例中为 coreLibrary)

mvn -am --projects webServices clean install 

【讨论】:

  • 我正在试验这个设置,到目前为止它运行良好。
  • 很高兴听到。请注意,第二个 pom 示例基本上就是您的 webServices 所拥有的。 swingApp 看起来大致相同,但具有不同的 artifactId。 coreLibrary 也会有一个不同的 artifactId 并且不会对你的任何项目有任何依赖,但你可能已经想通了。
  • 查找有关also-make 选项的更多信息,我发现了这个sonatype.com/people/2009/10/… 这正是我开始做的事情。
  • 是的,这就是我从中提取同样制作信息的链接。很有帮助。
【解决方案2】:

您不应该将 .jar 添加到您的项目中。您应该将 JAR 依赖项添加到您的 .pom 文件中。 Maven 将为您下载 .jars。您必须为每个内部 .jar 创建 .pom 文件,并将它们添加到您的 maven 存储库(或代理,如果有的话)。

【讨论】:

  • 我想我已经很好地掌握了这个概念。但你的回答并没有涵盖我关于日常编译的问题的后半部分。
  • 在 Maven 世界中,每当您在 CoreLibrary jar 中进行更改时,您都会“发布”它的新版本(实际上是将版本号提升了一个级别),然后更新依赖项目的引用新版本。 Maven 处理剩下的事情。
  • 您可能还想阅读 _SNAPSHOT 版本。在 POM 中使用快照版本可以让您在每次构建时告诉 maven 获取 .jar 的新副本(不增加版本号)。请务必删除最终版本的 _SNAPSHOT。
【解决方案3】:

从技术上讲,有多种解决方案可以实现此构建,但根据这些项目及其生命周期之间的耦合,您最终可能会选择其中一个选项。一些问题可能有助于做出决定:

  • 谁在建设所有这些项目?独特的团队?分开的团队?
  • SwingApp 和 WebServices 之间有什么关系吗?当您构建 SwingApp 时,构建 WebServices 是否有意义?当您发布 SwingApp 时,您是否也发布了 WebServices? SwingApp 和 WebServices 项目是否始终使用相同版本的 CoreLibrary?
  • 一起构建这 3 个项目有意义吗?
  • 单独构建 CoreLibrary 并让两个项目都依赖于生成的 jar 是否有意义?

根据提供的信息,我的理解(可能是错误的,这只是一种解释)是所有 3 个项目实际上是紧密耦合的,并且是由同一个人同时开发的。当核心库被修改时,依赖项目被重新构建。所以,我建议以下多模块项目:

my-app/ // 这是父模块,它聚合子模块 |-- pom.xml |-- 核心库 | `-- pom.xml |-- swing-app // 此模块依赖于 core-library | `-- pom.xml `-- web-services // 这个模块依赖于 core-library `-- pom.xml

想法是将所有项目放在一个父模块下,并同时使用项目聚合和项目继承:

  • 父项目将用于聚合子模块。它有一个pom 类型的包装,并声明了一个包含所有3 个子模块的&lt;modules&gt; 元素。 通过这样做,父项目现在知道它的模块,如果对父项目调用 Maven 命令,那么该 Maven 命令也将被执行到父项目的模块。
  • 每个子模块都将父项目声明为&lt;parent&gt;。这对于从父 pom 继承公共部分很有用
  • swing-app 和 web-services 模块将在其 pom.xml 中声明的 core-library 上有一个 &lt;dependency&gt;。在多模块构建期间,maven 使用依赖项来计算构建顺序。

通过此设置,当从顶级项目运行 Maven 时,core-library 将在 swing-appweb-services 之前构建(这称为多模块构建或反应堆构建)这似乎是所需的行为。因此,这似乎等同于没有混乱的本地 JAR 管理的实际情况(使用 maven,依赖项是通过“本地存储库”管理的,这是一个内置功能)。

注意:如果 NetBeans 不喜欢嵌套模块,则可以使用这样的平面布局(但现在更详细):

我的应用程序/ |-- 父级 | `-- pom.xml |-- 核心库 | `-- pom.xml |-- 摇摆应用 | `-- pom.xml `-- 网络服务 `-- pom.xml

对于实现细节,Multi Module Project with Eclipse 可能会帮助您快速入门,只需跳过 Eclipse 特定步骤即可。或者查看 Sonatype 的 Maven 书籍的 Chapter 6. A Multi-module Project 以获得“真实”参考。

【讨论】:

    【解决方案4】:

    让每个应用程序和 jar 库成为一个普通父级中的一个模块。让两个应用程序都依赖于核心,maven 会找出构建事物的顺序。

    【讨论】:

      【解决方案5】:

      我有两个顶级项目,一个是 Swing 应用程序,另一个是一组 Web 服务。它们都依赖于同一个内部 jar。

      您是否在使用自己的 Maven 存储库?如果是这样,最简单的选择是使用 POM 中的 &lt;dependency&gt; 元素简单地部署通用的内部 JAR 并让两个项目都依赖于 JAR。

      Nexus 是一个非常棒且易于使用的存储库,如果您要在内部使用 Maven,那么您无疑会想要运行自己的存储库,这样您就可以实际“发布”每个项目、库的版本JAR 等。Repository Management with Nexus 是 Sonatype 的免费书籍,详细介绍了如何使用它、最佳实践等。

      【讨论】:

      • 我实际上在找到 Nexus 之前就找到了 Artifactory 并让它运行起来。但在开始使用它之前,我会再看一遍。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-24
      • 2012-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多