【问题标题】:Maven Multi Module Project Structuring IssuesMaven 多模块项目结构问题
【发布时间】:2014-03-08 13:15:04
【问题描述】:

这是我在过去几周构建我的 maven 多模块项目以来的一次有趣经历。

当我决定使用 maven 进行构建生命周期管理时,我有几个原因希望选择 maven。

一个。大多数开发团队是分开的,以便每个团队可以在项目中的单独模块上工作,例如团队-A 负责用户管理系统,团队-B 负责授权系统,团队-C 负责文档管理系统......和很快。每个团队都有 Java 开发人员、测试人员、UI 专家等。

因此,maven 项目结构应该使得每个团队都可以独立地处理各自的模块。他们必须能够编码、编译、构建、测试、部署他们的模块,而无需编译、测试属于其他团队的模块。

因此我得出结论,maven 多模块项目的每个开发模块都必须代表一个功能模块

在论坛上进行了一些讨论后,我发现有人建议我遵循分层方法,子模块必须是控制器层、服务层、dao 层等层。我没有注意这个建议,因为这不能解决我的问题团队在单个模块上工作的目的。这样,对于大型项目,每个团队在开发过程中的构建和部署时间都会增加,这确实会影响项目时间线。如果项目中有 10 到 11 个模块,有时构建和部署时间长达 30 分钟。

但我确实注意到了一个建议,即为每个模块保留 DAO 层并不是一个好主意,因为 DAO 是高度精细的并且可以被其他模块重用。所以一个模块对另一个模块的依赖会变得更大。

我通过创建一个公共模块并将 DAO 和 DOMAIN 移动到公共模块中找到了解决此问题的方法,该公共模块将作为每个模块的依赖项继承。这似乎是一个更可行的选择。现在项目结构如下所示。

现在,当我构建项目并在服务器上运行 webapp 时,它会抱怨 404,找不到资源。我发现这是因为缺少 WEB-INF/classes 文件夹,web-app 模块中缺少 src/main/java。我搜索并发现了几个链接,表明它是 Eclipse 中的部署程序集问题。所以我需要手动创建这些文件夹并添加到部署程序集中,因为 maven 不这样做。

但更大的问题是

  1. 我是否需要将 com.mycompany.usermgmtsys.controller.UserMgmtController 等控制器类移动到 src/main/java 或者 maven 应该从作为依赖项包含在 WEB-INF/lib 中的模块 jar 中找到控制器。

我不想这样做,即将 java 文件放入 web-app。我希望所有控制器都可以作为依赖项提供给 Web 应用程序,例如 WEB-INF/lib/usermgmtsystem.jar。但是Tomcat不会在类文件夹中寻找控制器。

我不知道该怎么办?任何建议将不胜感激。

【问题讨论】:

  • 您希望您的控制器/服务依赖于您的网络应用程序?那是倒退。您的 Web 应用程序是您的客户端层,应该位于架构“堆栈”的顶部。它应该向下调用到服务层,然后将请求编排到其他服务和/或域层。
  • 在我的问题的任何地方,我并不是要颠倒依赖顺序。我所期望的只是让 web-app 从它在战争中打包的依赖 jar 中识别它的控制器,这样就没有 404。如果你看一下结构,我仍然有正确的依赖顺序,即 Common(它包含 DAO 和 DOMAIN ) 作为对 UserManagement 的依赖项,它作为对 Web-app 的依赖项。问题是因为我在各自的子模块中包含了各自的控制器,所以在 WEB-INF/classes 文件夹中找不到它们,而是在 WEB-INF/lib 中作为 jar 找到它们。
  • 因为是依赖jar,所以应该在WEB-INF/lib中。这是正确的行为。

标签: java eclipse spring maven tomcat


【解决方案1】:

它是 Eclipse 渲染基于 maven 的项目的方式。它通常创建两个结构。一种基于主 pom(父项目),另一种基于单个模块 pom。但是,对任何结构进行更改都会反映在另一个结构中。作为一种实践,我会更改各个模块的文件夹结构,并且也更易于阅读。

就我个人而言,我尽量避免使用多模块项目,因为如果您使用 Maven 发布插件,您将被锁定为一起发布所有模块。

虽然这听起来很方便,但当您需要对其中一个模块进行错误修复发布时就会出现问题 - 您最终会发布所有模块,而不仅仅是带有错误修复的模块,即使它们会增加它们的版本没变。

如果您使用多模块项目运行 CI,您也会受到打击 - 您的构建通常会从根 pom 运行所有模块,但如果您在特定模块中工作,您最终会受到打击构建那些没有改变的东西,实际上失去了模块化本应提供的一些好处。

所以,使用独立的模块,但是,这是重要的一点,创建每个使用的通用“依赖”pom。

“依赖”pom 是一个标准化所有项目依赖关系的 pom,不同之处在于这些依赖关系是在依赖项管理部分而不是依赖项部分中指定的(它还设置标准插件配置等)。这允许您的项目 pom 将依赖项 pom 指定为其父项,然后声明他们需要减去版本的依赖项,这些依赖项是从“依赖项”pom 中提取的,从而在您的项目中标准化。

如果您仍然担心能够构建所有内容,这可以通过一个简单的批处理文件来实现。

【讨论】:

    【解决方案2】:

    这是个好问题。有用的项目布局必须考虑许多方面。我想试着回答一个你没有提到的问题。您的应用程序是否可以由用户扩展?如果是,请考虑为您的公共 API 层(服务接口、这些服务使用的 DTO 以及服务抛出的异常)创建一个单独的模块。

    在我们的应用程序中,每个功能区域都有几个 maven 模块。这个想法是,一个小组只在一个功能区域内处理一个功能,这种隔离使他们与另一个小组正在修改的源代码混淆。每个功能区域在我们称为“api”、“域”和“服务”的 maven 子模块中进一步细分——我们不会将服务/控制器、域和异常集中到一个模块中。 api 模块包含我们想要向客户公开的那些类以供他们定制。我们的服务层是这些接口的实现。此外,我们不允许一个模块的服务调用另一个模块的服务,因为这会绕过我们的服务编排层,客户可以将扩展附加到我们的服务。每个功能区域使用单独的 Maven 模块有助于强制执行此操作。

    我们还有其他模块(internal-api、web、adapter),但它们并没有真正添加到这个主题中。

    【讨论】:

    • 我不知道我是否按预期理解了您的回复。但似乎即使我在做和你做的一样的事情,除了你在细分你的模块时要更高一层。在我的实际应用中,父模块有子模块(mediamanager-webapp、usermanagement、authorizationmanagement、documentmanagement、performancemanagement、reportsmanagement、notificationmanagement)。所以这些是按功能区域划分的。但似乎您已将模块进一步细分为子模块“域”和每个模块的服务。您的公共 api 与我的公共模块相同。
    • 这是我最初通过进一步细分的好方法。但是后来我认为这有点过头了,因为随着每个进一步的细分,还有一个额外的 Maven 配置,需要维护的弹簧配置。其次,即使我们也不鼓励一个服务调用另一个服务,这就是为什么公共模块提供所有模块的 DAO 层,以便可以重用粒度 DAO 层。理想情况下,如果您绘制一个具有表示->服务->数据访问的 3 层架构,您将看到该域不属于任何一层,而是属于公共层。
    • 为了方便管理这么多模块,我们使用“模板”POM 和 POM 继承。所有“api”模块都继承自一个 api 模板 POM,它使用 为所有 api 模块设置我们的插件配置。我们有服务、Web 服务、域等模板。
    【解决方案3】:

    我发现了这个问题。控制器是表示层组件。调度程序期望目标中的 WEB-INF/classes 文件夹中的表示层组件,而不是在 lib 中查找它。我不确定这是否仅对 Eclipse 中基于 Maven 的结构有效。所以最后这些是我所做的改变

    一个。在 web-app 中创建了一个 src/main/java 源文件夹。 web-app 模块中默认不生成它。 湾。在 src/main/java 文件夹中添加包和相应的控制器。

    所以我拥有的最终结构(我没有粘贴精确的 Eclipse 快照,这是概括视图)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-12
      • 2016-12-12
      • 1970-01-01
      • 2011-03-02
      • 2021-10-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多