【问题标题】:Maven Exec plugin, ClassLoader ClassNotFoundExceptionMaven Exec 插件,ClassLoader ClassNotFoundException
【发布时间】:2017-05-11 14:11:42
【问题描述】:

我在 StackOverflow 上尝试了许多建议,并使用 setup 和 pom.xml 的多种组合进行了 3 天的测试,但它们都不起作用。请帮忙。

我从一个有很多依赖项、spring-boot、hibernate 等的大项目开始。然后我创建了另一个小型控制台项目,它从大项目中导入和使用一些类。它们不是父子项目。我所做的就是将<dependency/> 添加到子项目pom 中,就像这样。 附言大项目有一个<parent/>spring-boot-starter-parent 并使用spring-boot-maven-plugin。

<dependency>
    <groupId>myGroup</groupId>
    <artifactId>bigProject</artifactId>
    <version>1.0.1</version>
</dependency>

这适用于带有 m2e 的 Eclipse,我只是使用“运行为”java 应用程序,并且这个小项目可以工作。 但我需要在我的 linux VM 上上传并运行这些项目,它不使用 GUI 和 Eclipse,只使用终端。

然后经过一番阅读,我尝试使用 maven exec 插件来运行这个小项目。我的步骤: 1.在大项目上做mvn clean install,确认它出现在我的/.m2,本地存储库中。 2. 在小项目上运行mvn compile 3. 在小项目上运行mvn exec:java 第2步失败,小项目抛出包xxx类中的import ...不存在。 maven 因编译错误而失败。

然后,我尝试简化问题。我创建了两个只有 1 个类的测试项目,myLib 和 HelloWorld 控制台应用程序,然后我添加了 myLib 依赖项(pom)。 HelloWorld 项目打印来自 myLib 包中的类的消息。运行步骤 1 到 3。它有效。

public class App 
{
    public static void main( String[] args )
    {
        //SystemLog from big project, does not work
        //SystemLog log = new SystemLog();
        //log.setValue("test value");
        //System.out.println(log.getValue());

        //CustomMessage from myLib, works fine      
        CustomMessage cm = new CustomMessage();
        cm.setTheMessage("custom message");
        System.out.println(cm.getTheMessage() );
        System.out.println(CustomMessage.defaultMsg);

    }
}

小项目的pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>test</groupId>
    <artifactId>dependOnOthers</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>dependOnOthers</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>test</groupId>
            <artifactId>myLibrary</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com</groupId>
            <artifactId>bigproject</artifactId>
            <version>1.0.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.5.0</version>
                <executions>
                    <execution>

                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <includePluginDependencies>true</includePluginDependencies>
                    <mainClass>test.dependOnOthers.App</mainClass>
                    <!-- <arguments> <argument>argument1</argument> </arguments> -->

                    <!-- <arguments> <argument>-classpath</argument> <argument>target/lib/bigproject-1.0.1.jar</argument> 
                        </arguments> -->
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

然后我添加了对大项目的引用,尝试使用 HelloWorld 打印一条日志消息,它通过了第 2 步,mvn 编译,但是当我执行第 3 步时,mvn exec:java,java.lang.ClassLoader.loadClass() 抛出 ClassNotFoundException 行我新建了一个 SystemLog() 实例,大项目中定义的类。

总结: 目标:尝试使用 Maven exec 插件运行控制台应用程序,该插件依赖于另一个项目,该项目安装在本地 repo /.m2 中 SystemLog 类是一个带有 hibernate 注释的模型类。 1.小项目依赖大项目,mvn编译失败,包不存在。 2. HelloWorld 依赖于 myLib,工作正常。 3. HelloWorld 依赖大项目,运行时失败,ClassNotFoundException。

【问题讨论】:

    标签: eclipse hibernate maven maven-plugin classnotfoundexception


    【解决方案1】:

    有点晚了,但我遇到了同样的错误,将项目从 1.5.3 迁移到 2.1.4

    我已经找到了解决这个问题的方法。

    Spring Boot 在 2.0.0+ 版本中改变了 jar 结构,所以你不需要将你的类指定为&lt;mainClass&gt;test.dependOnOthers.App&lt;/mainClass&gt;,你需要将 JarLauncher 指向主入口。

    插件执行jar的时候,java会调用main方法JarLauncher,然后会调用spring的几个代码,然后读取manifest,调用Start-Class:中定义的类。在你的情况下test.dependOnOthers.App.

    <configuration>
    <!-- Since version 2 of spring, the jar is packed in 
    another way and has his main method here, don't worry in the MANIFEST file is described which file to boot -->
    <mainClass>org.springframework.boot.loader.JarLauncher</mainClass>
    

    Spring 1.0 的旧结构,是经典的 java 方式,所以 java 类加载器可以毫无问题地加载它并在类路径中引用类,版本 2.0.0+,他们复制用户class 文件和依赖到 BOOT-INF 中,所以 java 类加载器无法加载,需要使用 Spring 类加载器来获取类实例。

    【讨论】:

      【解决方案2】:

      我有一个解决方法并且知道是什么导致了问题,但不知道所有细节,希望有人对此发表评论,或详细说明答案。

      导致这个问题的东西是spring-boot-maven-plugin,我用它来运行spring-boot嵌入式tomcat服务器,使用mvn spring-boot:run。这个插件似乎改变了 .jar 文件的某些内容,也许是清单?

      解决方法是删除此插件,运行mvn clean install,安装在本地存储库中的.jar 将正常工作。在小项目上运行mvn compile。然后将插件添加回大项目,运行mvn spring-boot:run

      我不知道插件更改了哪些导致带有包的 .jar 不存在,它是否更改了包名称?

      我的解决方法很笨拙,如果有一种方法可以通过定义 maven 目标来选择使用或不使用 spring-boot-maven-plugin 进行编译,这样我就不需要为不同的构建(带/不带插件)更改 pom。这将是一个更好的解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-10
        • 2015-07-29
        • 1970-01-01
        • 2018-04-12
        • 2018-12-25
        • 2016-12-08
        • 2016-03-08
        • 2011-08-10
        相关资源
        最近更新 更多