java 如何重构Maven多模块项目?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10452444/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to restructure Maven multi-module project?
提问by Eric B.
I appologize for the length of this post, but I had trouble making it more concise without presenting the picture. I've recently inherited the job of build-master for a maven 3.0 multi-module project. The problem is that the structure of the project/modules is a disaster. From the way things are currently stored in Source Control (we use RTC) to the pom structure of the modules, I'm tearing my hair out trying to get a full build cycle completed each time.
我为这篇文章的长度表示歉意,但我无法在不展示图片的情况下使其更加简洁。我最近为一个 maven 3.0 多模块项目继承了 build-master 的工作。问题是项目/模块的结构是一场灾难。从当前在源代码管理中存储的方式(我们使用 RTC)到模块的 pom 结构,我都在竭力尝试每次都完成一个完整的构建周期。
As a project hierarchy goes, all the modules are stored "flat"; ie: everything is at the same level. I have a parent pom, and all modules depend on the parent. However, the parent is at the same level as all my other modules.
随着项目层次结构的发展,所有模块都“扁平化”存储;即:一切都在同一水平上。我有一个父 pom,所有模块都依赖于父 pom。但是,父模块与我的所有其他模块处于同一级别。
Ex:
前任:
c:\dev\MyEarProject
+ parent-pom
- pom.xml
+ module1
- pom.xml (depends on parent-pom)
- src
- main
- ...
+ module2
- pom.xml (depends on parent-pom)
- src
- main
- ...
+ module3
- pom.xml (depends on parent-pom)
- src
- main
- ...
The parent pom defines all the modules required to build the project, as well as a bunch of properties for artifact version numbers used throughout the different submodules:
父 pom 定义了构建项目所需的所有模块,以及在不同子模块中使用的工件版本号的一堆属性:
<modules>
<module>../module1</module>
<module>../module2</module>
<module>../module3</module>
</modules>
<properties>
<org.springframework.version>3.0.5.RELEASE</org.springframework.version>
<slf4j.version>1.6.4</slf4j.version>
<repositoryAddress>${snapshots.repo.url}</repositoryAddress>
<my.hibernate-module.dao.impl>1.2.3</my.hibernate-module.dao.impl>
<my.hibernate-module.dao.api>1.2.3</my.hibernate-module.dao.api>
</properties>
Each module's pom, in turn, depends on the parent pom via the pom's artifact number:
反过来,每个模块的 pom 通过 pom 的工件编号取决于父 pom:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
</parent>
To make things even more confusing, the actual artifact name may, or may not (depending on the module), match the module path. For example, module1 may be located in path c:\dev\MyEarProject\module1
but have artifact name hibernate-module
. However, due to the way it is stored in RTC, the directory is called module1
when it is checked-out.
更令人困惑的是,实际的工件名称可能(取决于模块)与模块路径匹配,也可能不匹配。例如,module1 可能位于 pathc:\dev\MyEarProject\module1
但有 artifact name hibernate-module
。但是,由于它在 RTC 中的存储方式,目录module1
在检出时会被调用。
The easiest way to build everything, of course, is to go into c:\dev\MyEarProject\parent-pom\
and run mvn clean deploy
. This works fine when in SNAPSHOT mode as the SNAPSHOT repo allows for multiple deployments of the same artifact version. But in release mode, this fails.
当然,构建一切的最简单方法是进入c:\dev\MyEarProject\parent-pom\
并运行mvn clean deploy
. 这在 SNAPSHOT 模式下工作正常,因为 SNAPSHOT 存储库允许同一工件版本的多个部署。但是在发布模式下,这失败了。
This structure is causing 2 problems for me.
这种结构给我带来了两个问题。
- Everytime I need to make a version change to a property in the parent, I have to update the parent-pom version number, and all the child modules parent pom's version, and all the child modules version themselves (since the parent changed).
- Whenever I need to deploy a release cycle, mvn will throw an error if one of the modules has not changed since the last cycle and consequently cannot be redeployed to the same repo (the repo does not allow overwriting existing artifacts)
- 每次我需要对父级中的属性进行版本更改时,我都必须更新 parent-pom 版本号,以及所有子模块的父 pom 版本,以及所有子模块本身的版本(因为父级已更改)。
- 每当我需要部署一个发布周期时,如果其中一个模块自上一个周期以来没有更改,因此无法重新部署到同一个 repo(该 repo 不允许覆盖现有工件),则 mvn 将抛出错误
So I'm looking for the best way to restructure this project to avoid these problems. For the parent pom, I know I can use a relative path to point to the parent instead. However, given the "flat" structure of the modules, is this a recommended approach (ie: the parent pom relative path would be ../parent-pom/pom.xml - seems a little odd to me)? Additionally, given that the versioning control of the parent is independent of the modules, would using a relative path not just open the door to additional confusion (ie: there would be no way to know which version of the parent pom is associated with which version of the submodule).
所以我正在寻找重组这个项目的最佳方式来避免这些问题。对于父 pom,我知道我可以使用相对路径来指向父 pom。但是,鉴于模块的“扁平”结构,这是推荐的方法吗(即:父 pom 的相对路径是 ../parent-pom/pom.xml - 对我来说似乎有点奇怪)?此外,鉴于父级的版本控制独立于模块,使用相对路径不仅会打开更多混淆的大门(即:无法知道父 pom 的哪个版本与哪个版本相关联子模块)。
Secondly, how can I build the entire ear without encountering the deploy errors I am having? Since the artifact already exists in the repo, I don't need to rebuild and redeploy it. I tried using --projects but with the number of modules involved, it gets extremely difficult to manage.
其次,如何在不遇到部署错误的情况下构建整个耳朵?由于该工件已存在于 repo 中,因此我不需要重建和重新部署它。我尝试使用 --projects 但由于涉及的模块数量众多,管理起来非常困难。
回答by khmarbaise
The first thing I really recommend is to restructure the projects folders ...which means to have the projects folder represent the structure which means NOTflatten the structure.
我真正推荐的第一件事是重组项目文件夹......这意味着让项目文件夹代表结构,这意味着不要扁平化结构。
+-- parent-pom (pom.xml)
+--- module1 (pom.xml)
+--- module2 (pom.xml)
+--- module3 (pom.xml)
As a result of that the modules section your parent will be simplified like this:
因此,您的父模块部分将被简化如下:
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
</modules>
Furthermore the parent entries in your modules can be simplified as well like this:
此外,模块中的父条目也可以像这样简化:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
</parent>
...which brings me to the next point:
……这让我想到下一点:
If all your current project define their parent as above this is simply wrong, cause will try to find the parent within the repository and not in a upper level folder. In other words this is causing of much of your problems with releasing etc.
如果您当前的所有项目都将其父项定义为上述内容,则这完全是错误的,cause 将尝试在存储库中而不是在上层文件夹中找到父项。换句话说,这导致了您在发布等方面的许多问题。
If we would fix this problem it has to look like this which I can't recommend:
如果我们要解决这个问题,它必须看起来像这样,我不推荐:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
<relativePath>../parent-pom/pom.xml</relativePath>
</parent>
An other thing which I observe is that you don't use SNAPTSHOT
's which will be replaced by the release plugin during the release phase. And in relationship to that it will automatically change all versions in the appropriate parents etc.
我观察到的另一件事是您不使用SNAPTSHOT
's ,它会在发布阶段被发布插件替换。与此相关,它会自动更改相应父级中的所有版本等。
In ideal case your modules should look like this:
在理想情况下,您的模块应如下所示:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
</parent>
<artifactId>module-1</artifactId>
<!-- No Version or groupId -->
Cause all modules will inherit the version and groupId
from their parent. Sometimes it's useful or needed to change a modules groupId
but it's an exception.
因为所有模块都将继承版本和groupId
它们的父模块。有时更改模块很有用或需要,groupId
但这是一个例外。
On thing I reread is about the separate versioning of the parent. This simply does not make sense, cause it's the parent of their modules so put it into the same structure and of course the same VCS.
我重读的事情是关于父级的单独版本控制。这根本没有意义,因为它是其模块的父级,因此将其放入相同的结构中,当然还有相同的 VCS。
If you want to make some configuration/plugins versions, dependencies which should be used for other projects as well than make a separate corporate pom.xml
which is a separate project and will be separately released etc.
如果你想制作一些配置/插件版本,应该用于其他项目的依赖项,而不是制作一个单独的公司pom.xml
,这是一个单独的项目,将单独发布等。
After you finished your structure changes you can simply go into the parent-pom directory and do mvn clean package
or mvn release:prepare release:perform
from that folder and everything will simpler.
完成结构更改后,您只需进入 parent-pom 目录并执行mvn clean package
或mvn release:prepare release:perform
从该文件夹执行操作,一切都会变得更简单。
回答by cvanes
If you're publishing your POM, you'll have to release any updates but you don't need to modify POM versions by hand - you can update versions automatically using the versions plugin or the release plugin. I tend to prefer the release plugin as it'll commit to SCM for you too.
如果您要发布 POM,则必须发布任何更新,但无需手动修改 POM 版本 - 您可以使用版本插件或发布插件自动更新版本。我倾向于更喜欢发布插件,因为它也会为您提交 SCM。
mvn versions:set
http://mojo.codehaus.org/versions-maven-plugin/
http://mojo.codehaus.org/versions-maven-plugin/
mvn release:prepare release:perform
http://maven.apache.org/plugins/maven-release-plugin/
http://maven.apache.org/plugins/maven-release-plugin/
Your repository manager may also allow overwriting an existing version but it's better practice to just release a new version.
您的存储库管理器也可能允许覆盖现有版本,但最好只发布一个新版本。
I tend to prefer the flat module structure as it allows use of the parent folder to store common files e.g. checkstyle configuration. I also find it useful to share the group id across modules then name the module directory the same as the artifactId.
我倾向于更喜欢扁平模块结构,因为它允许使用父文件夹来存储常见文件,例如 checkstyle 配置。我还发现在模块之间共享组 ID 然后将模块目录命名为与 artifactId 相同的名称很有用。
回答by Pierre
You are presenting contradicting requirements. You want to restructure your project but can't move things around. You want to simplify your deployment and release cycles but do not want to use a single version.
您提出了相互矛盾的要求。您想重组您的项目,但无法移动。您希望简化部署和发布周期,但又不想使用单一版本。
Given that changes in one module will inevitably affect all of the dependent modules, I would use a simple version'ing scheme where all the sub-modules inherit their parent's version. maven release:prepare and release cycles become simple. Use a release notes to track your changes and justify skipping unnecessary testing of unchanged modules (changes to a version do not change the build/binary output of the build process so you can use that as your primary argument).
鉴于一个模块的更改将不可避免地影响所有依赖模块,我将使用一种简单的版本控制方案,其中所有子模块都继承其父模块的版本。maven 发布:准备和发布周期变得简单。使用发行说明来跟踪您的更改并证明跳过对未更改模块进行不必要的测试是合理的(对版本的更改不会更改构建过程的构建/二进制输出,因此您可以将其用作主要参数)。
Good luck with your project.
祝你的项目好运。