拆分一个大项目以创建一个多模块Maven项目


23

我正在开发一个Spring-MVC应用程序,其中我们使用Maven进行依赖项管理。由于项目规模很大,我们正在考虑将项目分为几个部分。我有一些疑问,希望能在这里得到答案。

当前,我们正在ROOT.war服务器上的Apache tomcat上部署单个WAR文件。由于项目规模很大,因此Web应用程序中包括通知和电子邮件,第三方服务,PUSH(Cometd),REST API等组件。目前,它们都是相互依存的,相互依赖。例如,Notification对象也取决于Person对象,因为通知是为用户量身定制的。

拆分大项目的主要目的是能够在单个模块上工作,进行错误修复,添加功能,进行测试等。如果满意,则只能在服务器上替换此模块,而不是整个应用程序。这可能吗?

如前所述,对象之间存在依赖关系和映射。如何在不同的子模块之间进行管理,或者只是将import语句更改为包括其他项目?

如我所说,其目的是在单个模块上工作并能够部署它们(最好是热的)。目前,我们只有一个WAR文件,如ROOT.war。拆分会创建多个war文件,然后将其称为URL domain-name.com/module_name/some_mapping吗?

我目前正在检查文档,但这是我们要使用Maven提供的多模块要实现的主要目标,并且想知道这是否可行。如果需要更多信息,请告诉我。

目前,我正在使用Spring的父POM,如下所示:

<parent>
    <groupId>io.spring.platform</groupId>
    <artifactId>platform-bom</artifactId>
    <version>1.1.3.RELEASE</version>
    <relativePath />
</parent>

1
我留给别人回答。这个想法很合理。您可以从具有dependencyManagement的父POM开始,然后为像Person这样的DAO罐子。一个非常基本的库。等等。当然没有循环依赖性。
乔普·艾根

Answers:


20

可能吗 ?

是的,当然了。过去,我有一些这样的项目,希望在这里能有所帮助。

您将使用Maven的两个主要功能将事物编织在一起:

分而治之

您将需要将您的项目拆分为多个独立的项目。这里所说的独立是指对项目外部代码的所有引用都是通过Maven中的依赖关系完成的,而不是直接合并源代码树。

根据源代码树的状态,这可能需要进行大量工作。那就是说,您不是在为Maven拔腿而做,而是作为结构化和清理代码库的一种手段。将其视为您的工具集,在这里更容易找到它们:

不错的工具棚

比这里:

不太好的工具架

Maven高度依赖约定,因此您的资料越有条理,Maven就可以为您提供更多帮助。就是说,可能需要您重新组织以更好地适应它自己的约定,并且如果我在这里不得不提出一个建议,那就是更改内容以适合Maven的约定要比尝试配置Maven容易得多。了解您的约定。

如果这些项目可以在主应用程序之外使用,那么它们可以作为真正的独立库运行,并包含maven依赖项。它们应位于自己的存储库中(而不是在应用程序源树中),并且不应依赖于主应用程序的任何部分。

应用程序的核心部分(一旦拆分为项目)可以放在一起作为模块。通常,您会将它们放置为应用程序主源文件夹的子文件夹。

同样,您的应用程序的父POM将包含模块声明。您还将在其中放置应用程序的所有常见依赖关系,并声明大多数构建插件及其配置。我在这里也建议您放置一组属性,例如可以在模块中重用的应用程序版本等。当所有版本具有相同版本并将版本放在一个位置时,这将更容易管理。

工装

如果您的团队规模大于1,我也强烈建议您为Maven依赖项安装一个存储库。看看ArtifactoryNexusArchiva。您可以将POM文件配置为直接安装到这些文件,因此一旦运行它就不会有太大的开销,但是可以节省您的团队大量时间,用正确的jar来解决依赖关系。

关于工具,下一步的逻辑步骤是一个持续集成系统(Jenkins,还有更多)。它将负责构建运行测试的源代码并推送至工件,所有这些都只需编写代码,其余代码即可工作。

由于您将应用打包为战争专家,因此无需合并jar文件或其他类似的工作,即可处理战争并将所有依赖项放置在适当的位置,因此不必担心。

我可以在这里继续更长的时间,但是没有什么比一个好的榜样更好了。在github上查找类似规模的项目,并查看它们如何构建pom文件和文件夹层次结构。观察不止一种,有些会比其他更适合您的设置,没有什么能真正体现真相,但您应该找到足够的力量来激发关于如何完成它的想法。

詹金斯为例:

您可以看到他们的父POM相当广泛。

它们确实使用模块,如您在本节中所见:

<modules>
    <module>core</module>
    <module>war</module>
    <module>test</module>
    <module>cli</module>
</modules>

每个模块对应一个具有相同名称的子文件夹,该子文件夹还包含一个POM。您可以像这样嵌套任意数量,尽管可以将其保持在合理水平内;)。

从小开始

如果您从未使用过Maven,我建议您不要立即开始使用模块。慢慢来,先说一个您可能拥有的较简单的库,然后使其成为Maven项目。然后将您的主应用程序变成一个简单的maven项目。一旦完成,开始添加简单的依赖关系,然后拆分第一个模块,依此类推。

Maven是一个很棒的工具,但是它也可能会给脖子带来极大的痛苦,尤其是当事情进展不顺利时。从您第一次尝试的整个过程开始,就是灾难的根源(对我而言!)。

如果事情有点怪异,您可以始终使用mvn help:effective-pom命令查看Maven实际理解的内容。

外挂程式

从您的评论中,我可以更好地理解您想要实现的目标。在这种情况下,我会选择插件方法。创建一个项目,该项目公开要隔离工作的扩展点的API。然后,您可以将其用作将要实现它的新项目中的依赖项。在您的主应用程序中,只需为这些实现添加适当的依赖项(这次不使用Maven模块),那么您应该一切顺利。最终,主应用程序项目几乎不会携带任何源代码,这些代码都是在外部项目中完成并通过依赖项加载的。

但是,您将需要使用这种方法重新部署整个应用程序,而不管内核是否更改,因为战争是从依赖关系静态构建的,更改其中一个依赖关系意味着重新构建整个事物。听起来比实际情况更糟。实际上,实际上只会构建新的更改,其余的基本上是以前的jar的副本。但是由于所有内容都在war文件中,因此将需要重新构建它,并且需要停止并重新启动服务器。

如果您需要更进一步,事情会变得有些复杂,尽管并非没有可能。我建议您研究OSGI ,尽管还有其他实现,但是Apache Felix可以帮助您入门。这将允许您将外部jar放入适当的插件中。您将获得对组件运行时生命周期的更多控制,从而为动态重新加载和更新打开了方便之门。但是,这将需要对核心进行重大更改,因此,这可能不是一个好的起点。但是,一旦您的项目被很好地分隔开并且所有部分都按照您想要的方式隔离开了,那么如果在更新时启动和停止应用程序是一个主要问题,那么下一步就很自然了。

模块和依赖项之间的基本区别是:

  • 模块将作为主文件夹位于与主应用程序相同的源代码树中。
  • 依赖关系可以在任何地方。

你可以在这里找到圣经。

希望这有帮助,祝你好运。


实际上,通过maven而不是源代码树来捆绑模块解决了我的很多问题。您能告诉我有关此类项目的部署情况吗?我们正在考虑的另一个原因之一是,开发人员可以处理所需的模块并实时进行更改。除了核心模块,我们希望避免的一件事是停止应用程序服务器并重新启动。我可以想到的2个模块将包含经常更改的代码。我们使用tomcat作为应用程序服务器,由Apache进行负载平衡。谢谢。
我们是博格

Maven模块通常与主应用程序位于同一源代码树中。实际上,在源代码树之外使用Maven模块要比实际值复杂得多。如果您确实在源代码树之外托管项目,则应使用普通的独立项目并使用普通的依赖项。
Newtopian

我认为我们将直接将项目的一部分添加为Maven依赖项。这样,我们可以直接处理部分项目。我只有一个问题,如果我们将一个子项目添加为POM.xml中的依赖项(例如版本2.0.0),然后进行一些更改,那么将模块2.0.1推入声纳类型,我们如何直接告诉核心模块使用2.0.1,只需更改ROOT.war中的POM.xml并删除ROOT目录就足够了。主要目的是不停止服务器。谢谢。
我们是博格

一旦创建了战争,pom.xml便完全没有关系,也就是说Tomcat(或您使用的任何容器)不使用此文件。Maven使用该文件来创建新的war文件,而您又必须将其部署到服务器。因此,该循环就是处理代码,创建jar文件,更新war的POM中的版本,创建war文件,并使用新的war文件更新服务器。某些服务器将支持热重新部署,尽管通常这将意味着关闭应用程序几秒钟。
Newtopian
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.