Java 在多模块Maven项目中共享公共模块

Java 在多模块Maven项目中共享公共模块,java,maven,spring-boot,pom.xml,spring-boot-maven-plugin,Java,Maven,Spring Boot,Pom.xml,Spring Boot Maven Plugin,我有一个项目,有三个模块:a、B和COMMON。 我想将公共逻辑放在公共模块(例如模型)中,然后是其他两个依赖于它的模块 这两个模块(A、B)将分别构建,以创建两个不同的JAR 我正在测试它,试图将日志依赖关系放在公共模块中,然后构建一个项目。它将正确构建,但如果我尝试使用“java-jar a.jar”运行jar,它将失败,并发现一个NoClassDefFound: Exception in thread "main" java.lang.NoClassDefFoundError: org/s

我有一个项目,有三个模块:a、B和COMMON。 我想将公共逻辑放在公共模块(例如模型)中,然后是其他两个依赖于它的模块

这两个模块(A、B)将分别构建,以创建两个不同的JAR

我正在测试它,试图将日志依赖关系放在公共模块中,然后构建一个项目。它将正确构建,但如果我尝试使用“java-jar a.jar”运行jar,它将失败,并发现一个NoClassDefFound:

Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
根pom:

<modules>
    <module>common</module>
    <module>a</module>
</modules>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.3</version>
        </dependency>
    </dependencies>
</dependencyManagement>

常见的
A.
org.slf4j
slf4j api
1.7.12
回写
回归经典
1.1.3
常见的pom:

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
    </dependency>
</dependencies>

org.slf4j
slf4j api
回写
回归经典
以及pom:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>bla.bla.Main</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

<dependencies>
    <dependency>
        <groupId>bla.blu</groupId>
        <artifactId>common</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

org.apache.maven.plugins
maven jar插件
2.4
真的
解放党/
布拉。布拉。梅因
布拉·布鲁
常见的
0.0.1-快照

当您试图从依赖于公共功能的.jar运行某些东西时,需要在类路径中包含公共模块。简单地将其声明为依赖项将不包括a.jar工件中的公共类(如果需要,您需要使用assembly maven插件)

此外,公共jar带来的所有可传递依赖也应该列在类路径中

因此,您必须像java-cp common.jar:slf4j-a.b.c.jar:logback-x.y.jar[:…]-jar a.jar那样运行它


Maven本身和任何知道Maven的IDE都会为您这样做,所以您不必手动完成。为了在生产中构建单个jar,您应该考虑使用或插件,并构建一个“胖”(或uber)jar,它将包含单个文件中的所有依赖项。默认情况下,

不将所有依赖项打包到jar中。因此它是缺失的。您希望在运行该jar时在类路径上提供该jar

另一个选择是创建所谓的胖罐子

顺便说一句,我备份了@Boris the Spider对Spring Boot的评论。走那条路,很多问题都会迎刃而解

编辑-对第一条评论的反应:

通常,公共依赖项应该部署到工件库(Nexus,Artifactory)中,并作为任何第三方依赖项从那里获取


由于您没有这样做,在构建A期间,您需要在本地存储库中具有公共依赖项。因此,将Spring boot maven插件放入一个构建中,并在您的多模块项目中构建胖jar。

除非您构建uber jar或显式导出依赖项,否则这将不起作用。我目前的偏好是使用魔法,将一个jar及其所有库打包,而不提取它们并将它们打包到一个jar中。除非
common.jar
是一个uber jar,否则我认为这不会起作用。@Boristeider显然,
common.jar
本身的依赖项也应该列在类路径中。如果这是你的观点,你完全正确。我只是试图简化事情,并假设没有可传递的依赖关系,只是为了回答具体的问题;但是当然,建议的命令行很可能会出现其他的
NoClassDefFoundError
s。但是这个问题是关于可传递依赖项(slf4j和logback)的,因此简化否定了答案的有用性…@Boristeider是的,我的错!我想我很少关注实际缺少的类,而是关注“公共”jar部分。我将尝试编辑答案。谢谢很酷!我添加了Spring Boot,一切似乎都“自动”运行。似乎我无论如何都无法构建“每个”模块。如果我尝试从根pom“打包”,它会工作。但如果我尝试打包COMMON,然后再打包A,它将为COMMON引发一个“无法解析依赖项”。可以吗?我必须建造所有的东西吗?