4

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

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

我正在测试它试图将日志依赖项放在 COMMON 模块中,然后构建 A 项目。它会正确构建,但如果我尝试使用“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>

常见的pom:

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

和一个 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>
4

2 回答 2

2

默认情况下,Maven 不会将所有依赖项打包到您的 JAR 中。因此它丢失了。当您运行它时,您应该在类路径上提供该 jar。

其他选择是创建所谓的胖罐。这是SO线程如何做到这一点

顺便说一句,我备份了@Boris the Spider 关于 Spring Boot 的评论。走这条路,很多问题都会开箱即用地为你解决。

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

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

由于您不这样做,因此您需要在构建 A 期间在本地存储库中具有共同的依赖关系。因此,将 Spring-boot-maven-plugin 放入 A 构建并使用您的多模块项目构建 fat jar。

于 2015-09-02T11:36:03.270 回答
0

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

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

所以你必须像java -cp common.jar:slf4j-a.b.c.jar:logback-x.y.jar[:...] -jar a.jar.

Maven 本身和任何知道 maven 的 IDE 都会为您执行此操作,因此您不必手动操作。为了构建单个 jar 以在生产中运行,您应该考虑使用程序集shade插件并构建一个“胖”(或 uber-)jar,它将在单个文件中包含所有依赖项。

于 2015-09-02T11:33:16.087 回答