我已经在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,我只使用&#34; Run as&#34; 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>
然后我添加对big 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而失败。
答案 0 :(得分:1)
有点晚了,但我遇到了同样的错误,将项目从1.5.3迁移到2.1.4
我找到了解决此问题的方法。
Spring Boot在2.0.0+版本中更改了jar结构,因此您无需将类指定为<mainClass>test.dependOnOthers.App</mainClass>
,只需将JarLauncher指向主入口即可。
当插件执行jar时,java将调用主要方法JarLauncher,并在他读取清单并调用Start-Class:
中定义的类之后调用spring的几个代码。就您而言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+版本引用该类时,它们会复制用户类文件和相关性进入BOOT-INF中,因此java类加载器无法再加载它,您需要使用Spring类加载器来获取类实例。
答案 1 :(得分:0)
我有一个解决方法,知道导致问题的原因,但不知道所有细节,希望有人会对此发表评论,或详细说明答案。
导致此问题的是spring-boot-maven-plugin
,我使用mvn spring-boot:run
来运行spring-boot嵌入式tomcat服务器。这个插件似乎改变了.jar文件,可能是清单?
解决方法是删除此插件,运行mvn clean install
,安装在本地存储库中的.jar将正常运行。在小项目上运行mvn compile
。然后将插件添加回大项目,运行mvn spring-boot:run
我不知道插件更改会导致包含不存在的.jar,它是否会更改包名称?
我的解决方法很笨拙,如果有一种方法可以选择使用或不使用spring-boot-maven-plugin
进行编译来定义maven目标,这样我就不需要为不同的构建更改pom(使用/不使用插件)。那将是一个更好的解决方案。