Maven多模块项目结构问题

时间:2014-02-10 23:41:15

标签: java eclipse spring maven tomcat

这是一个有趣的经历,我在过去几周构建了我的maven多模块项目。

当我决定使用maven进行构建生命周期管理时,我有几个理由想要选择maven。

一个。大多数开发团队都是分开的,这样每个团队都可以在项目中的单独模块上工作,比如Team-A来处理用户管理系统,Team-B来处理授权系统,Team-C来处理文档管理系统......以及等等。每个团队都有java开发人员,测试人员,UI专家等。

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

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

PROJECT STRUCTURE 1

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

但是我确实注意到为每个模块保持DAO层分离的建议不是一个好主意,因为DAO非常精细并且被其他模块重用。因此,一个模块对其他模块的依赖性将会变得更大。

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

PROJECT STRUCTURE 2

现在当我构建项目并在服务器上运行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中找到控制器。
  2. 我不想这样做,即将java文件放在web-app中。我希望所有控制器都可以作为依赖项用于web-app,例如WEB-INF / lib / usermgmtsystem.jar。但那么Tomcat不会在类文件夹中寻找控制器。

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

3 个答案:

答案 0 :(得分:1)

它是eclipse渲染基于maven的项目的方式。它通常创建两个结构。一个基于主pom(父项目)和其他基于单个模块pom。但是,任何结构的变化都会反映在另一个结构中。作为一种练习,我对单个模块文件夹结构进行了更改,也更容易阅读。

就我个人而言,我试图避免使用多模块项目,因为如果您使用Maven Release Plugin,您将无法一起发布所有模块。

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

如果您使用多模块项目运行CI,您也会受到欢迎 - 您的构建通常会在您的根pom上运行所有模块,但如果您在特定模块中工作,你最终会把那些没有改变的东西打造成生机,实际上会失去模块化所带来的一些好处。

所以,请使用独立模块,但这是重要的一点,创建一个共同的依赖'每个人使用的pom。

A'依赖' pom是一个标准化项目中所有依赖项的pom,不同之处在于依赖项是在dependencyManagement部分而不是依赖项部分中指定的(它还设置了标准的插件配置等)。这允许您的项目poms将依赖项pom指定为其父项,然后声明它们所需的依赖项减去从“依赖项”中获取的版本。 pom并因此在您的项目中实现标准化。

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

答案 1 :(得分:0)

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

在我们的应用程序中,每个功能区域都有几个maven模块。我们的想法是,一个小组只在一个功能区域内处理一个功能,而这种隔离让他们弄乱了被另一个组修改的源。每个功能区域在我们称为“api”,“域”和“服务”的maven子模块中进一步细分 - 我们不会将服务/控制器,域和异常集中到单个模块中。 api模块包含我们希望向客户公开其自定义的类。我们的服务层是这些接口的实现。此外,我们不允许一个模块的服务调用另一个模块的服务,因为这会绕过我们的服务编排层,客户可以在其中附加我们服务的扩展。每个功能区域使用单独的maven模块有助于实现这一点。

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

答案 2 :(得分:0)

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

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

所以我拥有的最终结构(我没有粘贴精确的eclipse快照,这是一般化的视图)

Final Structure